Created
December 4, 2021 09:48
-
-
Save bibekblockchain/69309b3320d916b4cd0b76c5928123c2 to your computer and use it in GitHub Desktop.
Flat Sale Proxy for Demons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scilla_version 0 | |
import ListUtils | |
library FlatDistributorProxy | |
let zero = Uint128 0 | |
(* Error events *) | |
type Error = | |
| CodeNotAdmin | |
| CodeNotStagingAdmin | |
| CodeNotWhitelisted | |
let bystr20_eq: ByStr20 -> ByStr20 -> Bool = | |
fun(e1 : ByStr20) => | |
fun(e2 : ByStr20) => | |
builtin eq e1 e2 | |
let is_whitelisted_address:List ByStr20 -> ByStr20 -> Bool = | |
fun (whitelist : List ByStr20) => | |
fun (address : ByStr20) => | |
let inside = bystr20_eq address in | |
let is_available = @list_exists ByStr20 in | |
is_available inside whitelist | |
let one_msg = | |
fun (m: Message) => | |
let e = Nil {Message} in | |
Cons {Message} m e | |
let make_error = | |
fun (result : Error) => | |
let result_code = | |
match result with | |
| CodeNotAdmin => Int32 -1 | |
| CodeNotStagingAdmin => Int32 -2 | |
| CodeNotWhitelisted => Int32 -3 | |
end | |
in | |
{ _exception : "Error"; code : result_code } | |
contract FlatDistributorProxy( | |
init_implementation: ByStr20, | |
init_admin: ByStr20 | |
) | |
(* Mutable fields *) | |
field implementation: ByStr20 = init_implementation | |
field admin: ByStr20 = init_admin | |
field stagingadmin: Option ByStr20 = None {ByStr20} | |
field whiteListedAddress: List (ByStr20) = Nil {ByStr20} | |
(* Emit Errors *) | |
procedure ThrowError(err : Error) | |
e = make_error err; | |
throw e | |
end | |
(***************************************************) | |
(* Transition *) | |
(***************************************************) | |
(***************************************************) | |
(* Proxy Transition *) | |
(***************************************************) | |
transition UpgradeTo(new_implementation: ByStr20) | |
currentAdmin <- admin; | |
isAdmin = builtin eq currentAdmin _sender; | |
match isAdmin with | |
| True => | |
implementation := new_implementation; | |
e = {_eventname: "Upgraded"; implementation: new_implementation}; | |
event e | |
| False => | |
err = CodeNotAdmin; | |
ThrowError err | |
end | |
end | |
transition ClaimProxyAdmin() | |
staging_admin_o <- stagingadmin; | |
match staging_admin_o with | |
| Some staging_admin => | |
is_stagingadmin = builtin eq staging_admin _sender; | |
match is_stagingadmin with | |
| True => | |
admin := _sender; | |
tmp_staging_admin = None {ByStr20}; | |
stagingadmin := tmp_staging_admin; | |
e = {_eventname: "ClaimProxyAdmin"; newAdmin: _sender}; | |
event e | |
| False => | |
err = CodeNotStagingAdmin; | |
ThrowError err | |
end | |
| None => | |
err = CodeNotStagingAdmin; | |
ThrowError err | |
end | |
end | |
transition UpdateWhiteListedAddress(whitelist: List ByStr20) | |
currentAdmin <- admin; | |
isAdmin = builtin eq currentAdmin _sender; | |
match isAdmin with | |
| True => | |
whiteListedAddress := whitelist; | |
e = {_eventname: "UpdateWhiteListedAddress"; list: whitelist}; | |
event e | |
| False => | |
err = CodeNotAdmin; | |
ThrowError err | |
end | |
end | |
(***************************************************) | |
(* House keeping transition *) | |
(***************************************************) | |
transition Buy() | |
whiteList <- whiteListedAddress; | |
is_whitelisted = is_whitelisted_address whiteList _sender; | |
match is_whitelisted with | |
| True => | |
accept; | |
impl <- implementation; | |
msg = {_tag: "Buy"; _recipient: impl; _amount: _amount; initiator: _sender}; | |
msgs = one_msg msg; | |
send msgs | |
| False => | |
err = CodeNotWhitelisted; | |
ThrowError err | |
end | |
end | |
transition BuyDemonWithDMZ() | |
whiteList <- whiteListedAddress; | |
is_whitelisted = is_whitelisted_address whiteList _sender; | |
match is_whitelisted with | |
| True => | |
accept; | |
impl <- implementation; | |
msg = {_tag: "BuyDemonWithDMZ"; _recipient: impl; _amount: zero; initiator: _sender}; | |
msgs = one_msg msg; | |
send msgs | |
| False => | |
err = CodeNotWhitelisted; | |
ThrowError err | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scilla_version 0 | |
(***************************************************) | |
(* Associated library *) | |
(***************************************************) | |
import BoolUtils IntUtils | |
library FiatDistributor | |
(* Error events *) | |
type Error = | |
| CodeNotMain | |
| CodeInsufficientFunds | |
| CodeNotContractOwner | |
| CodeNotFound | |
| CodePauseNotPause | |
| CodeInvalidPaymentMode | |
| CodeProxyValidationFailed | |
let not_pause = Uint32 0 | |
let on_pause = Uint32 1 | |
let zero256 = Uint256 0 | |
let zero128 = Uint128 0 | |
let one256 = Uint256 1 | |
let one128 = Uint128 1 | |
let payment_mode_zil = Uint32 1 | |
let payment_mode_dmz = Uint32 2 | |
let one_msg = | |
fun (msg : Message) => | |
let nil_msg = Nil {Message} in | |
Cons {Message} msg nil_msg | |
let make_error = | |
fun (result : Error) => | |
let result_code = | |
match result with | |
| CodeNotMain => Int32 -1 | |
| CodeInsufficientFunds => Int32 -2 | |
| CodeNotContractOwner => Int32 -3 | |
| CodeNotFound => Int32 -4 | |
| CodePauseNotPause => Int32 -5 | |
| CodeInvalidPaymentMode => Int32 -6 | |
| CodeProxyValidationFailed => Int32 -7 | |
end | |
in | |
{ _exception : "Error"; code : result_code } | |
let option_value = | |
tfun 'A => | |
fun (default: 'A) => | |
fun (opt_val: Option 'A) => | |
match opt_val with | |
| Some v => v | |
| None => default | |
end | |
let option_uint128 = @option_value Uint128 | |
let get_count = | |
fun (a: Uint128) => | |
fun (p: Uint128) => | |
builtin div a p | |
let change_of_coins = | |
fun (count: Uint128) => | |
fun (price: Uint128) => | |
fun (amount: Uint128) => | |
let is_one = builtin eq count one128 in | |
match is_one with | |
| True => zero128 | |
| False => | |
builtin sub amount price | |
end | |
(***************************************************) | |
(* The contract definition *) | |
(***************************************************) | |
contract FiatDistributor | |
( | |
contract_owner: ByStr20, | |
init_wallet: ByStr20, | |
init_dmz: ByStr20, | |
init_proxy_address: ByStr20, | |
main: ByStr20 with contract | |
field token_id_count: Uint256 | |
end | |
) | |
(* Mutable fields *) | |
field owner: ByStr20 = contract_owner | |
field pending_owner: Option ByStr20 = None {ByStr20} | |
field dmz: ByStr20 = init_dmz | |
field wallet: ByStr20 = init_wallet | |
field pause: Uint32 = on_pause | |
field payment_mode: Uint32 = payment_mode_dmz | |
(* Total token count *) | |
field reserve: Uint256 = zero256 | |
field total: Uint256 = zero256 | |
field tokens_reserve: Map Uint256 String = Emp Uint256 String | |
field decimal: Uint256 = Uint256 25 | |
field price: Uint128 = Uint128 450000000000000000000 | |
field buy_incentive: Uint128 = Uint128 200000000000000000000 | |
(* Emit Errors *) | |
procedure ThrowError(err : Error) | |
e = make_error err; | |
throw e | |
end | |
procedure IsContractOwner() | |
current_owner <- owner; | |
is_contract_owner = builtin eq current_owner _sender; | |
match is_contract_owner with | |
| True => | |
| False => | |
err = CodeNotContractOwner; | |
ThrowError err | |
end | |
end | |
procedure IsMain() | |
is_main_contract = builtin eq main _sender; | |
match is_main_contract with | |
| True => | |
| False => | |
err = CodeNotMain; | |
ThrowError err | |
end | |
end | |
(* Check if the caller is the proxy *) | |
procedure IsProxy() | |
is_proxy = builtin eq _sender init_proxy_address; | |
match is_proxy with | |
| True => | |
| False => | |
err = CodeProxyValidationFailed; | |
ThrowError err | |
end | |
end | |
procedure AddFunds(recipient: ByStr20, amount: Uint128) | |
is_zero = builtin eq amount zero128; | |
match is_zero with | |
| False => | |
msg = { | |
_tag: "AddFunds"; | |
_recipient: recipient; | |
_amount: amount | |
}; | |
msgs = one_msg msg; | |
send msgs | |
| True => | |
end | |
end | |
procedure CheckPause(expected: Uint32) | |
curent_pause <- pause; | |
is_eq = builtin eq expected curent_pause; | |
match is_eq with | |
| True => | |
| False => | |
err = CodePauseNotPause; | |
ThrowError err | |
end | |
end | |
procedure CheckPaymentMode(expected: Uint32) | |
current_payment_mode <- payment_mode; | |
is_eq = builtin eq expected current_payment_mode; | |
match is_eq with | |
| True => | |
| False => | |
err = CodeInvalidPaymentMode; | |
ThrowError err | |
end | |
end | |
procedure Minting(to: ByStr20) | |
total_reserve <- reserve; | |
some_uri <- tokens_reserve[total_reserve]; | |
match some_uri with | |
| Some uri => | |
msg_to_demons = { | |
_tag: "Mint"; | |
_recipient: main; | |
_amount: Uint128 0; | |
to: to; | |
token_uri: uri | |
}; | |
msgs = one_msg msg_to_demons; | |
send msgs; | |
new_total_reserve = builtin sub total_reserve one256; | |
reserve := new_total_reserve; | |
delete tokens_reserve[total_reserve] | |
| None => | |
err = CodeNotFound; | |
ThrowError err | |
end | |
end | |
procedure AddReserve(uri: String) | |
count_reserve <- reserve; | |
new_count_reserve = builtin add count_reserve one256; | |
tokens_reserve[new_count_reserve] := uri; | |
reserve := new_count_reserve | |
end | |
procedure CallTransferFrom(amount: Uint128, from: ByStr20, to: ByStr20) | |
dmz_o <- dmz; | |
call_transfer_from = { | |
_tag: "TransferFrom"; | |
_recipient: dmz_o; | |
_amount: Uint128 0; | |
from: from; | |
to: to; | |
amount: amount | |
}; | |
msgs = one_msg call_transfer_from; | |
send msgs | |
end | |
(* @dev Updates the token image uri list; used by contract owner. *) | |
(* @param token_uris_list: image URI list in REVERSE order, 20.jpg, 19.jpg...01.jpg *) | |
transition AddReserveList(token_uris_list: List String) | |
IsContractOwner; | |
forall token_uris_list AddReserve | |
end | |
(* @dev Updates the starting price; used by contract owner. *) | |
(* @param value: new starting price in Qa *) | |
transition ChangePrice(value: Uint128) | |
IsContractOwner; | |
price := value; | |
e = {_eventname: "ChangePrice"; new_price: value}; | |
event e | |
end | |
(* @dev Updates the constant factor; used by contract owner. *) | |
(* @param value: new decimal value *) | |
transition ChangeDecimal(value: Uint256) | |
IsContractOwner; | |
decimal := value; | |
e = {_eventname: "ChangeDecimal"; new_decimal: value}; | |
event e | |
end | |
(* @dev Updates the incentive received when buying demon; used by contract owner. *) | |
(* @param value: new buy incentive value in DMZ decimal places *) | |
transition ChangeIncentive(value: Uint128) | |
IsContractOwner; | |
buy_incentive := value; | |
e = {_eventname: "ChangeIncentive"; new_buy_incentive: value}; | |
event e | |
end | |
(* @dev Buy a demon with ZILs. *) | |
(* contract must be unpaused first *) | |
(* Price of demon is set by math model. Users will get refund if they pay more than necessary. *) | |
transition Buy(initiator: ByStr20) | |
IsProxy; | |
CheckPause not_pause; | |
CheckPaymentMode payment_mode_zil; | |
total_supply <- total; | |
decimal_value <- decimal; | |
price_value <- price; | |
count = get_count _amount price_value; | |
is_zero = builtin eq count zero128; | |
match is_zero with | |
| True => | |
err = CodeInsufficientFunds; | |
ThrowError err | |
| False => | |
accept; | |
comm_wallet <- wallet; | |
incentive <- buy_incentive; | |
change = change_of_coins count price_value _amount; | |
AddFunds initiator change; | |
Minting initiator; | |
CallTransferFrom incentive comm_wallet initiator | |
end | |
end | |
(* @dev Buy a demon with DMZ. *) | |
(* contract must be unpaused first. payment mode must change to DMZ *) | |
(* Price of demon is set by math model. *) | |
transition BuyDemonWithDMZ(initiator: ByStr20) | |
IsProxy; | |
CheckPause not_pause; | |
CheckPaymentMode payment_mode_dmz; | |
total_supply <- total; | |
decimal_value <- decimal; | |
price_value <- price; | |
comm_wallet <- wallet; | |
incentive <- buy_incentive; | |
(* transfer dmz to comm wallet *) | |
CallTransferFrom price_value initiator comm_wallet; | |
Minting initiator; | |
CallTransferFrom incentive comm_wallet initiator | |
end | |
(* @dev Drain contract balance to comm wallet; used only by contract owner *) | |
transition DrainContractBalance() | |
IsContractOwner; | |
bal <- _balance; | |
wallet_o <- wallet; | |
AddFunds wallet_o bal | |
end | |
(* @dev Pause or unpause the contract; used only by contract owner *) | |
transition UpdatePause() | |
IsContractOwner; | |
status <- pause; | |
is_pause = builtin eq status on_pause; | |
match is_pause with | |
| True => | |
pause := not_pause | |
| False => | |
pause := on_pause | |
end; | |
updated_pause <- pause; | |
e = {_eventname : "UpdatePause"; pause: updated_pause}; | |
event e | |
end | |
(* @dev Updates the payment mode when buying demons; zil or dmz; used only by contract owner *) | |
transition UpdatePaymentMode(new_payment_mode: Uint32) | |
IsContractOwner; | |
is_gte_first = uint32_ge new_payment_mode payment_mode_zil; | |
is_lte_last = uint32_le new_payment_mode payment_mode_dmz; | |
is_within_range = andb is_gte_first is_lte_last; | |
match is_within_range with | |
| True => | |
payment_mode := new_payment_mode | |
| False => | |
err = CodeInvalidPaymentMode; | |
ThrowError err | |
end; | |
updated_payment_mode <- payment_mode; | |
e = {_eventname : "UpdatePaymentMode"; payment_mode: updated_payment_mode}; | |
event e | |
end | |
(* @dev Updates the dmz contract address; used only by contract owner *) | |
transition UpdateDMZ(new_dmz: ByStr20) | |
IsContractOwner; | |
dmz := new_dmz; | |
e = {_eventname: "UpdateDMZ"; new_dmz: new_dmz}; | |
event e | |
end | |
(* @dev Updates the wallet contract address; used only by contract owner *) | |
transition UpdateWallet(new_wallet: ByStr20) | |
IsContractOwner; | |
wallet := new_wallet; | |
e = {_eventname: "UpdateWallet"; new_wallet: new_wallet}; | |
event e | |
end | |
(* @dev: Sets a new contract owner; used by contract owner only. *) | |
(* Current owner can abort the process by calling this transition with their own address *) | |
(* @param: new_owner New owner address *) | |
transition RequestOwnershipTransfer(new_owner: ByStr20) | |
IsContractOwner; | |
po = Some {ByStr20} new_owner; | |
pending_owner := po; | |
e = {_eventname: "RequestOwnershipTransfer"; new_owner: new_owner}; | |
event e | |
end | |
(* @dev: New owner accepts the ownership transfer request; used by the new owner only. *) | |
transition ConfirmOwnershipTransfer() | |
optional_po <- pending_owner; | |
match optional_po with | |
| Some pend_owner => | |
caller_is_new_owner = builtin eq _sender pend_owner; | |
match caller_is_new_owner with | |
| True => | |
(* transfer ownership *) | |
owner := pend_owner; | |
none = None {ByStr20}; | |
pending_owner := none; | |
e = {_eventname: "ConfirmOwnershipTransfer"; new_owner: pend_owner}; | |
event e | |
| False => | |
(* caller is not the new owner, do nothing *) | |
err = CodeNotContractOwner; | |
ThrowError err | |
end | |
| None => | |
(* ownership transfer is not in-progress, do nothing *) | |
end | |
end | |
(* callbacks *) | |
(* Buy -> Minting -> Mint (demon_contract) -> MintCallBack *) | |
transition MintCallBack(recipient: ByStr20, token_id: Uint256, token_uri: String) | |
IsMain; | |
current_count <- total; | |
new_count = builtin add current_count one256; | |
total := new_count; | |
e = {_eventname : "MintDemonSuccess"; minted: new_count}; | |
event e | |
end | |
(* Buy -> Minting -> CallTransferFrom *) | |
transition TransferFromSuccessCallBack(initiator: ByStr20, sender: ByStr20, recipient: ByStr20, amount: Uint128) | |
end | |
(* callbacks *) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment