Smart Contract Details
Open on Dero ExplorerInternal ID:
84
Hash / Transaction:
Block:
Timestamp:
2022-07-10 22:47:40 UTC (3.2 years ago)
Creator:
…qq3gdj6x
(1391510)
Raw Data:
[{"name":"SC_ACTION","datatype":"U","value":1},{"name":"SC_CODE","datatype":"S","value":"//\r\n//Multisig wallet! Written by thedudelebowski for the Dero smart contract competition!\r\n//Version 2.0 - Competition entry 2021\r\n//Check out https://github.com/lebowski1234/dero-multisig-2021 for setup and usage instructions. \r\n// \r\n//This instance of the multisig was developed by secretnamebasis for the DE! community\r\n//\r\n\r\n// This function is used to initialize parameters during install time\r\nFunction Initialize() Uint64\r\n10 STORE(\"txCount\", 0) \r\n20 userSetup(SIGNER())\r\n30 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function userSetup: Contains all variables which must be set by the person deploying the contract.\r\nFunction userSetup(signer String) Uint64\r\n10 STORE(\"numberOfOwners\", 3) //Must match number of non-blank \"owner\" fields below. \r\n20 STORE(\"authorizationConsensus\", 2) //Number of owners that must sign before a transaction is authorized. Can be 1 to No. of owners. \r\n30 STORE(\"owner1\", signer) // DE! wallet\r\n//Add additional owners below if more than 6 owners required. \r\n40 STORE(\"owner2\", ADDRESS_RAW(\"dero1qy2jy9yjj50w2vgdefhssn738qdu8fdt58nnmm8lt7kx6msaey0n2qqtwluyy\")) // rpc wallet\r\n50 STORE(\"owner3\", ADDRESS_RAW(\"dero1qyvqpdftj8r6005xs20rnflakmwa5pdxg9vcjzdcuywq2t8skqhvwqglt6x0g\")) // hot-wallet\r\n90 STORE(\"error\", \"setup complete\") \r\n100 RETURN 0\r\nEnd Function\r\n\r\n\r\n\r\n//Entrypoint functions:\r\n\r\n//Function Deposit: This entrypoint function is called to deposit funds into the wallet. \r\nFunction Deposit() Uint64\r\n10 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function Send: Create a new transaction. To is a Dero address, Amount is the amount to send from the wallet balance. \r\nFunction Send(To String, Amount Uint64) Uint64\r\n10 DIM ownerNo, txCount as Uint64\r\n50 LET ownerNo = sendChecks(To, Amount, SIGNER())\r\n60 IF ownerNo != 0 THEN GOTO 80\r\n70 RETURN 0 //Initial checks failed, exiting\r\n80 storeTx(To, Amount, ownerNo)\r\n90 storeSigners()\r\n100 LET txCount = LOAD(\"txCount\")\r\n110 STORE(\"tx\" + txCount + \"_signer\" + ownerNo, 1) //Transaction originator signs transaction automatically\r\n120 LET txCount = txCount + 1\r\n130 STORE(\"txCount\", txCount)\r\n140 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function Sign: The main sign function. Signs transaction ID, and sends Dero if required number of signatures has been reached. \r\nFunction Sign(ID Uint64) Uint64\r\n10 DIM ownerNo as Uint64\r\n50 LET ownerNo = signChecks(SIGNER())\r\n60 IF ownerNo != 0 THEN GOTO 80\r\n70 RETURN 0 //Initial checks failed, exiting\r\n80 sign(ID, ownerNo)\r\n90 IF authorized(ID) == 0 THEN GOTO 110 //In this case, 0 = true, as authorized must return 0 to store values within function.\r\n100 RETURN 0 //Not yet authorized, exiting\r\n110 sendDero(ID)//Send Dero \r\n120 RETURN 0\r\nEnd Function\r\n\r\n\r\n\r\n//The following functions are called by the main functions, to break up the code into easy to read sections. \r\n\r\n\r\n//Function sendChecks: sequence of checks to perform before transaction is accepted.\r\nFunction sendChecks(to String, amount Uint64, signer String) Uint64\r\n10 DIM ownerNo as Uint64\r\n20 IF sendValid(to, amount) == 1 THEN GOTO 30 \r\n25 RETURN 0\r\n30 LET ownerNo = verifySigner(signer)\r\n40 IF ownerNo != 0 THEN GOTO 60\r\n50 RETURN 0\r\n60 RETURN ownerNo //All checks passed, return owner No. to calling function. \r\nEnd Function\r\n\r\n\r\n//Function signChecks: sequence of checks to perform before signing request is accepted.\r\nFunction signChecks(signer String) Uint64\r\n10 DIM ownerNo as Uint64\r\n20 LET ownerNo = verifySigner(signer)\r\n30 IF ownerNo != 0 THEN GOTO 50\r\n35 STORE(\"error\", \"failed at signChecks L35\") //for debug only\r\n40 RETURN 0\r\n50 RETURN ownerNo //All checks passed, return owner No. to calling function. \r\nEnd Function\r\n\r\n\r\n//Function sendValid: Checks whether Send transaction parameters are valid.\r\nFunction sendValid(s String, i Uint64) Uint64\r\n10 IF IS_ADDRESS_VALID(ADDRESS_RAW(s)) == 1 THEN GOTO 40\r\n20 STORE(\"error\", \"failed at sendValid L20 - recipient not a valid Dero address\") //for debug only\r\n30 RETURN 0 //Basic format check has failed, exit\r\n40 IF i \u003e0 THEN GOTO 70\r\n50 STORE(\"error\", \"failed at sendValid L50 - Amount to send is zero, not a valid transaction\") //for debug only\r\n60 RETURN 0 //Basic format check has failed, exit\r\n70 RETURN 1\r\nEnd Function\r\n\r\n\r\n//Function verifySigner: Check that signer is an owner. \r\nFunction verifySigner(s String) Uint64\r\n10 DIM inc, numberOfOwners as Uint64\r\n30 LET numberOfOwners = LOAD(\"numberOfOwners\") //ok up to here!\r\n40 LET inc = 1\r\n50 IF s == LOAD(\"owner\" + inc) THEN GOTO 110 \r\n60 IF inc == numberOfOwners THEN GOTO 90 //we have reached numberOfOwners, and not matched the signers address to an owner.\r\n70 LET inc = inc + 1\r\n80 GOTO 50\r\n90 STORE(\"error\", \"failed at verifySigner L90 - Signer address not found in list of owners\") //for debug only\r\n100 RETURN 0 //Signer ownership check has failed, result is 0. Calling functon must exit on 0. \r\n110 RETURN inc //Signer is in list of owners, return owner index.\r\nEnd Function\r\n\r\n\r\n//Function storeTx: store a new transaction in the DB\r\nFunction storeTx(to String, amount Uint64, owner Uint64) Uint64\r\n10 DIM txCount, ownerNo as Uint64\r\n20 LET txCount = LOAD(\"txCount\")\r\n30 STORE(\"txIndex_\"+txCount, txCount) \r\n40 STORE(\"recipient_\"+txCount, to)\r\n50 STORE(\"amount_\"+txCount, amount)\r\n60 STORE(\"sent_\"+txCount, 0) //Not sent yet\r\n70 STORE(\"signatures_\"+txCount, 1) //Set to 1 immediately as originator signs as part of transaction creation\r\n80 RETURN 0\r\nEnd Function \r\n\r\n\r\n//Function storeSigners: setup (store) signer fields for a new transaction, based on current txCount.\r\nFunction storeSigners() Uint64\r\n10 DIM txCount, ownerNo, numberOfOwners as Uint64\r\n20 LET txCount = LOAD(\"txCount\")\r\n30 LET numberOfOwners = LOAD(\"numberOfOwners\")\r\n40 LET ownerNo = 1\r\n50 STORE(\"tx\" + txCount + \"_signer\" + ownerNo , 0)\r\n60 IF ownerNo == numberOfOwners THEN GOTO 90\r\n70 LET ownerNo = ownerNo + 1\r\n80 GOTO 50\r\n90 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function sendDero: Retrieve transaction from ID No, send Dero, mark transaction as sent. \r\nFunction sendDero(ID Uint64) Uint64\r\n10 DIM isSent, amount as Uint64\r\n11 DIM to as String\r\n20 LET isSent = LOAD(\"sent_\" + ID)\r\n30 IF isSent == 0 THEN GOTO 60\r\n40 STORE(\"error\", \"failed at sendDero L40 - Transaction has already been sent\") //for debug only\r\n50 RETURN 0\r\n60 LET amount = LOAD(\"amount_\" + ID)\r\n70 LET to = LOAD(\"recipient_\" + ID)\r\n90 SEND_DERO_TO_ADDRESS(ADDRESS_RAW(to), amount) \r\n100 STORE(\"sent_\" + ID, 1) //mark tx as sent\r\n110 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function authorized: Counts number of signatures for a transaction, and compares with consensus. Returns 1 if consensus reached.\r\nFunction authorized(ID Uint64) Uint64\r\n10 DIM authCount, isSigned, ownerNo, numberOfOwners, authorizationConsensus as Uint64\r\n20 LET numberOfOwners = LOAD(\"numberOfOwners\")\r\n30 LET authorizationConsensus = LOAD(\"authorizationConsensus\")\r\n40 LET ownerNo = 1\r\n50 LET isSigned = LOAD(\"tx\" + ID + \"_signer\" + ownerNo)\r\n60 LET authCount = authCount + isSigned\r\n70 IF ownerNo == numberOfOwners THEN GOTO 100\r\n80 LET ownerNo = ownerNo + 1\r\n90 GOTO 50\r\n100 IF authCount \u003e= authorizationConsensus THEN GOTO 140\r\n120 RETURN 1\r\n140 RETURN 0\r\nEnd Function\r\n\r\n\r\n//Function sign: check TX ID exists, then sign TX if owner has not already signed\r\nFunction sign(ID Uint64, owner Uint64) Uint64\r\n10 DIM isSigned, signatures as Uint64\r\n20 IF EXISTS(\"tx\" + ID + \"_signer\" + owner) THEN GOTO 50\r\n30 STORE(\"error\", \"failed at sign L30 - Transaction ID not found\") //for debug only\r\n40 RETURN 0\r\n50 LET isSigned = LOAD(\"tx\" + ID + \"_signer\" + owner)\r\n60 IF isSigned == 0 THEN GOTO 90 //Transaction is not yet signed for this owner.\r\n70 STORE(\"error\", \"failed at sign L30 - Transaction already signed for owner \" + owner) //for debug only\r\n80 RETURN 0\r\n90 STORE(\"tx\" + ID + \"_signer\" + owner, 1)//Sign transaction for this owner.\r\n91 LET signatures = LOAD(\"signatures_\"+ID) \r\n92 STORE(\"signatures_\"+ID, signatures + 1) //increment signature count - for user interface\r\n110 RETURN 0\r\nEnd Function\r\n\r\n"}]
Code:
//
//Multisig wallet! Written by thedudelebowski for the Dero smart contract competition!
//Version 2.0 - Competition entry 2021
//Check out https://github.com/lebowski1234/dero-multisig-2021 for setup and usage instructions.
//
//This instance of the multisig was developed by secretnamebasis for the DE! community
//
// This function is used to initialize parameters during install time
Function Initialize() Uint64
10 STORE("txCount", 0)
20 userSetup(SIGNER())
30 RETURN 0
End Function
//Function userSetup: Contains all variables which must be set by the person deploying the contract.
Function userSetup(signer String) Uint64
10 STORE("numberOfOwners", 3) //Must match number of non-blank "owner" fields below.
20 STORE("authorizationConsensus", 2) //Number of owners that must sign before a transaction is authorized. Can be 1 to No. of owners.
30 STORE("owner1", signer) // DE! wallet
//Add additional owners below if more than 6 owners required.
40 STORE("owner2", ADDRESS_RAW("dero1qy2jy9yjj50w2vgdefhssn738qdu8fdt58nnmm8lt7kx6msaey0n2qqtwluyy")) // rpc wallet
50 STORE("owner3", ADDRESS_RAW("dero1qyvqpdftj8r6005xs20rnflakmwa5pdxg9vcjzdcuywq2t8skqhvwqglt6x0g")) // hot-wallet
90 STORE("error", "setup complete")
100 RETURN 0
End Function
//Entrypoint functions:
//Function Deposit: This entrypoint function is called to deposit funds into the wallet.
Function Deposit() Uint64
10 RETURN 0
End Function
//Function Send: Create a new transaction. To is a Dero address, Amount is the amount to send from the wallet balance.
Function Send(To String, Amount Uint64) Uint64
10 DIM ownerNo, txCount as Uint64
50 LET ownerNo = sendChecks(To, Amount, SIGNER())
60 IF ownerNo != 0 THEN GOTO 80
70 RETURN 0 //Initial checks failed, exiting
80 storeTx(To, Amount, ownerNo)
90 storeSigners()
100 LET txCount = LOAD("txCount")
110 STORE("tx" + txCount + "_signer" + ownerNo, 1) //Transaction originator signs transaction automatically
120 LET txCount = txCount + 1
130 STORE("txCount", txCount)
140 RETURN 0
End Function
//Function Sign: The main sign function. Signs transaction ID, and sends Dero if required number of signatures has been reached.
Function Sign(ID Uint64) Uint64
10 DIM ownerNo as Uint64
50 LET ownerNo = signChecks(SIGNER())
60 IF ownerNo != 0 THEN GOTO 80
70 RETURN 0 //Initial checks failed, exiting
80 sign(ID, ownerNo)
90 IF authorized(ID) == 0 THEN GOTO 110 //In this case, 0 = true, as authorized must return 0 to store values within function.
100 RETURN 0 //Not yet authorized, exiting
110 sendDero(ID)//Send Dero
120 RETURN 0
End Function
//The following functions are called by the main functions, to break up the code into easy to read sections.
//Function sendChecks: sequence of checks to perform before transaction is accepted.
Function sendChecks(to String, amount Uint64, signer String) Uint64
10 DIM ownerNo as Uint64
20 IF sendValid(to, amount) == 1 THEN GOTO 30
25 RETURN 0
30 LET ownerNo = verifySigner(signer)
40 IF ownerNo != 0 THEN GOTO 60
50 RETURN 0
60 RETURN ownerNo //All checks passed, return owner No. to calling function.
End Function
//Function signChecks: sequence of checks to perform before signing request is accepted.
Function signChecks(signer String) Uint64
10 DIM ownerNo as Uint64
20 LET ownerNo = verifySigner(signer)
30 IF ownerNo != 0 THEN GOTO 50
35 STORE("error", "failed at signChecks L35") //for debug only
40 RETURN 0
50 RETURN ownerNo //All checks passed, return owner No. to calling function.
End Function
//Function sendValid: Checks whether Send transaction parameters are valid.
Function sendValid(s String, i Uint64) Uint64
10 IF IS_ADDRESS_VALID(ADDRESS_RAW(s)) == 1 THEN GOTO 40
20 STORE("error", "failed at sendValid L20 - recipient not a valid Dero address") //for debug only
30 RETURN 0 //Basic format check has failed, exit
40 IF i >0 THEN GOTO 70
50 STORE("error", "failed at sendValid L50 - Amount to send is zero, not a valid transaction") //for debug only
60 RETURN 0 //Basic format check has failed, exit
70 RETURN 1
End Function
//Function verifySigner: Check that signer is an owner.
Function verifySigner(s String) Uint64
10 DIM inc, numberOfOwners as Uint64
30 LET numberOfOwners = LOAD("numberOfOwners") //ok up to here!
40 LET inc = 1
50 IF s == LOAD("owner" + inc) THEN GOTO 110
60 IF inc == numberOfOwners THEN GOTO 90 //we have reached numberOfOwners, and not matched the signers address to an owner.
70 LET inc = inc + 1
80 GOTO 50
90 STORE("error", "failed at verifySigner L90 - Signer address not found in list of owners") //for debug only
100 RETURN 0 //Signer ownership check has failed, result is 0. Calling functon must exit on 0.
110 RETURN inc //Signer is in list of owners, return owner index.
End Function
//Function storeTx: store a new transaction in the DB
Function storeTx(to String, amount Uint64, owner Uint64) Uint64
10 DIM txCount, ownerNo as Uint64
20 LET txCount = LOAD("txCount")
30 STORE("txIndex_"+txCount, txCount)
40 STORE("recipient_"+txCount, to)
50 STORE("amount_"+txCount, amount)
60 STORE("sent_"+txCount, 0) //Not sent yet
70 STORE("signatures_"+txCount, 1) //Set to 1 immediately as originator signs as part of transaction creation
80 RETURN 0
End Function
//Function storeSigners: setup (store) signer fields for a new transaction, based on current txCount.
Function storeSigners() Uint64
10 DIM txCount, ownerNo, numberOfOwners as Uint64
20 LET txCount = LOAD("txCount")
30 LET numberOfOwners = LOAD("numberOfOwners")
40 LET ownerNo = 1
50 STORE("tx" + txCount + "_signer" + ownerNo , 0)
60 IF ownerNo == numberOfOwners THEN GOTO 90
70 LET ownerNo = ownerNo + 1
80 GOTO 50
90 RETURN 0
End Function
//Function sendDero: Retrieve transaction from ID No, send Dero, mark transaction as sent.
Function sendDero(ID Uint64) Uint64
10 DIM isSent, amount as Uint64
11 DIM to as String
20 LET isSent = LOAD("sent_" + ID)
30 IF isSent == 0 THEN GOTO 60
40 STORE("error", "failed at sendDero L40 - Transaction has already been sent") //for debug only
50 RETURN 0
60 LET amount = LOAD("amount_" + ID)
70 LET to = LOAD("recipient_" + ID)
90 SEND_DERO_TO_ADDRESS(ADDRESS_RAW(to), amount)
100 STORE("sent_" + ID, 1) //mark tx as sent
110 RETURN 0
End Function
//Function authorized: Counts number of signatures for a transaction, and compares with consensus. Returns 1 if consensus reached.
Function authorized(ID Uint64) Uint64
10 DIM authCount, isSigned, ownerNo, numberOfOwners, authorizationConsensus as Uint64
20 LET numberOfOwners = LOAD("numberOfOwners")
30 LET authorizationConsensus = LOAD("authorizationConsensus")
40 LET ownerNo = 1
50 LET isSigned = LOAD("tx" + ID + "_signer" + ownerNo)
60 LET authCount = authCount + isSigned
70 IF ownerNo == numberOfOwners THEN GOTO 100
80 LET ownerNo = ownerNo + 1
90 GOTO 50
100 IF authCount >= authorizationConsensus THEN GOTO 140
120 RETURN 1
140 RETURN 0
End Function
//Function sign: check TX ID exists, then sign TX if owner has not already signed
Function sign(ID Uint64, owner Uint64) Uint64
10 DIM isSigned, signatures as Uint64
20 IF EXISTS("tx" + ID + "_signer" + owner) THEN GOTO 50
30 STORE("error", "failed at sign L30 - Transaction ID not found") //for debug only
40 RETURN 0
50 LET isSigned = LOAD("tx" + ID + "_signer" + owner)
60 IF isSigned == 0 THEN GOTO 90 //Transaction is not yet signed for this owner.
70 STORE("error", "failed at sign L30 - Transaction already signed for owner " + owner) //for debug only
80 RETURN 0
90 STORE("tx" + ID + "_signer" + owner, 1)//Sign transaction for this owner.
91 LET signatures = LOAD("signatures_"+ID)
92 STORE("signatures_"+ID, signatures + 1) //increment signature count - for user interface
110 RETURN 0
End Function