pangolindex / exchange-contracts

GNU General Public License v3.0
94 stars 65 forks source link

Pangolindex fork #29

Closed Rydamez closed 1 year ago

Rydamez commented 2 years ago

​// File: contracts/Factory.sol

​pragma solidity​ ​^​0.4.15​;

​contract​ ​Factory​ {

​    ​/ ​       Events ​     */ ​    ​event ​ContractInstantiation​(​address​ ​sender​, ​address​ ​instantiation​);

​    ​/ ​       Storage ​     */ ​    ​mapping​(​address​ ​=>​ ​bool​) ​public​ isInstantiation; ​    ​mapping​(​address​ ​=>​ ​address​[]) ​public​ instantiations;

​    ​/ ​      Public functions ​     */ ​    ​/// @dev Returns number of instantiations by creator. ​    ​/// @param creator Contract creator. ​    ​/// @return Returns number of instantiations by creator. ​    ​function​ getInstantiationCount​(​address​ ​creator​) ​        ​public ​        ​constant ​        ​returns​ (​uint​) ​    { ​        ​return​ instantiations[creator].length; ​    }

​    ​/ ​      Internal functions ​     */ ​    ​/// @dev Registers contract in factory registry. ​    ​/// @param instantiation Address of contract instantiation. ​    ​function​ register​(​address​ ​instantiation​) ​        ​internal ​    { ​        isInstantiation[instantiation] ​=​ ​true​; ​        instantiations[​msg​.​sender​].​push​(instantiation); ​        ​ContractInstantiation​(​msg​.​sender​, instantiation); ​    } ​}

​// File: contracts/MultiSigWallet.sol

​pragma solidity​ ​^​0.4.15​;

​/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. ​/// @author Stefan George - stefan.george@consensys.net ​contract​ ​MultiSigWallet​ {

​    ​/ ​       Events ​     */ ​    ​event ​Confirmation​(​address​ ​indexed​ ​sender​, ​uint​ ​indexed​ ​transactionId​); ​    ​event ​Revocation​(​address​ ​indexed​ ​sender​, ​uint​ ​indexed​ ​transactionId​); ​    ​event ​Submission​(​uint​ ​indexed​ ​transactionId​); ​    ​event ​Execution​(​uint​ ​indexed​ ​transactionId​); ​    ​event ​ExecutionFailure​(​uint​ ​indexed​ ​transactionId​); ​    ​event ​Deposit​(​address​ ​indexed​ ​sender​, ​uint​ ​value​); ​    ​event ​OwnerAddition​(​address​ ​indexed​ ​owner​); ​    ​event ​OwnerRemoval​(​address​ ​indexed​ ​owner​); ​    ​event ​RequirementChange​(​uint​ ​required​);

​    ​/ ​       Constants ​     */ ​    ​uint​ ​constant public ​MAX_OWNER_COUNT ​=​ ​50​;

​    ​/ ​       Storage ​     */ ​    ​mapping​ (​uint​ ​=>​ Transaction) ​public​ transactions; ​    ​mapping​ (​uint​ ​=>​ ​mapping​ (​address​ ​=>​ ​bool​)) ​public​ confirmations; ​    ​mapping​ (​address​ ​=>​ ​bool​) ​public​ isOwner; ​    ​address​[] ​public​ owners; ​    ​uint​ ​public​ required; ​    ​uint​ ​public​ transactionCount;

​    ​struct​ Transaction​ { ​        ​address​ destination; ​        ​uint​ value; ​        ​bytes​ data; ​        ​bool​ executed; ​    }

​    ​/ ​       Modifiers ​     */ ​    ​modifier​ onlyWallet​() { ​        ​require​(​msg​.​sender​ ​==​ ​address​(​this​)); ​        ​_; ​    }

​    ​modifier​ ownerDoesNotExist​(​address​ ​owner​) { ​        ​require​(​!​isOwner[owner]); ​        ​_; ​    }

​    ​modifier​ ownerExists​(​address​ ​owner​) { ​        ​require​(isOwner[owner]); ​        ​_; ​    }

​    ​modifier​ transactionExists​(​uint​ ​transactionId​) { ​        ​require​(transactions[transactionId].destination ​!=​ ​0​); ​        ​_; ​    }

​    ​modifier​ confirmed​(​uint​ ​transactionId​, ​address​ ​owner​) { ​        ​require​(confirmations[transactionId][owner]); ​        ​_; ​    }

​    ​modifier​ notConfirmed​(​uint​ ​transactionId​, ​address​ ​owner​) { ​        ​require​(​!​confirmations[transactionId][owner]); ​        ​_; ​    }

​    ​modifier​ notExecuted​(​uint​ ​transactionId​) { ​        ​require​(​!​transactions[transactionId].executed); ​        ​_; ​    }

​    ​modifier​ notNull​(​address​ ​_address​) { ​        ​require​(address ​!=​ ​0​); ​        ​; ​    }

​    ​modifier​ validRequirement​(​uint​ ​ownerCount​, ​uint​ ​_required​) { ​        ​require​(ownerCount ​<=​ MAX_OWNER_COUNT ​            ​&&​ _required ​<=​ ownerCount ​            ​&&​ required ​!=​ ​0 ​            ​&&​ ownerCount ​!=​ ​0​); ​        ​; ​    }

​    ​/// @dev Fallback function allows to deposit ether. ​    ​function​() ​        ​payable ​    { ​        ​if​ (​msg​.​value​ ​>​ ​0​) ​            ​Deposit​(​msg​.​sender​, ​msg​.​value​); ​    }

​    ​/ ​      Public functions ​     */ ​    ​/// @dev Contract constructor sets initial owners and required number of confirmations. ​    ​/// @param _owners List of initial owners. ​    ​/// @param _required Number of required confirmations. ​    ​function​ MultiSigWallet​(​address​[] ​_owners​, ​uint​ ​_required​) ​        ​public ​        ​validRequirement​(_owners.length, _required) ​    { ​        ​for​ (​uint​ i​=​0​; i​<​_owners.length; i​++​) { ​            ​require​(​!​isOwner[_owners[i]] ​&&​ _owners[i] ​!=​ ​0​); ​            isOwner[_owners[i]] ​=​ ​true​; ​        } ​        owners ​=​ _owners; ​        required ​=​ _required; ​    }

​    ​/// @dev Allows to add a new owner. Transaction has to be sent by wallet. ​    ​/// @param owner Address of new owner. ​    ​function​ addOwner​(​address​ ​owner​) ​        ​public ​        onlyWallet ​        ​ownerDoesNotExist​(owner) ​        ​notNull​(owner) ​        ​validRequirement​(owners.length ​+​ ​1​, required) ​    { ​        isOwner[owner] ​=​ ​true​; ​        owners.​push​(owner); ​        ​OwnerAddition​(owner); ​    }

​    ​/// @dev Allows to remove an owner. Transaction has to be sent by wallet. ​    ​/// @param owner Address of owner. ​    ​function​ removeOwner​(​address​ ​owner​) ​        ​public ​        onlyWallet ​        ​ownerExists​(owner) ​    { ​        isOwner[owner] ​=​ ​false​; ​        ​for​ (​uint​ i​=​0​; i​<​owners.length ​-​ ​1​; i​++​) ​            ​if​ (owners[i] ​==​ owner) { ​                owners[i] ​=​ owners[owners.length ​-​ ​1​]; ​                ​break​; ​            } ​        owners.length ​-=​ ​1​; ​        ​if​ (required ​>​ owners.length) ​            ​changeRequirement​(owners.length); ​        ​OwnerRemoval​(owner); ​    }

​    ​/// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. ​    ​/// @param owner Address of owner to be replaced. ​    ​/// @param newOwner Address of new owner. ​    ​function​ replaceOwner​(​address​ ​owner​, ​address​ ​newOwner​) ​        ​public ​        onlyWallet ​        ​ownerExists​(owner) ​        ​ownerDoesNotExist​(newOwner) ​    { ​        ​for​ (​uint​ i​=​0​; i​<​owners.length; i​++​) ​            ​if​ (owners[i] ​==​ owner) { ​                owners[i] ​=​ newOwner; ​                ​break​; ​            } ​        isOwner[owner] ​=​ ​false​; ​        isOwner[newOwner] ​=​ ​true​; ​        ​OwnerRemoval​(owner); ​        ​OwnerAddition​(newOwner); ​    }

​    ​/// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet. ​    ​/// @param _required Number of required confirmations. ​    ​function​ changeRequirement​(​uint​ ​_required​) ​        ​public ​        onlyWallet ​        ​validRequirement​(owners.length, _required) ​    { ​        required ​=​ _required; ​        ​RequirementChange​(_required); ​    }

​    ​/// @dev Allows an owner to submit and confirm a transaction. ​    ​/// @param destination Transaction target address. ​    ​/// @param value Transaction ether value. ​    ​/// @param data Transaction data payload. ​    ​/// @return Returns transaction ID. ​    ​function​ submitTransaction​(​address​ ​destination​, ​uint​ ​value​, ​bytes​ ​data​) ​        ​public ​        ​returns​ (​uint​ ​transactionId​) ​    { ​        transactionId ​=​ ​addTransaction​(destination, value, data); ​        ​confirmTransaction​(transactionId); ​    }

​    ​/// @dev Allows an owner to confirm a transaction. ​    ​/// @param transactionId Transaction ID. ​    ​function​ confirmTransaction​(​uint​ ​transactionId​) ​        ​public ​        ​ownerExists​(​msg​.​sender​) ​        ​transactionExists​(transactionId) ​        ​notConfirmed​(transactionId, ​msg​.​sender​) ​    { ​        confirmations[transactionId][​msg​.​sender​] ​=​ ​true​; ​        ​Confirmation​(​msg​.​sender​, transactionId); ​        ​executeTransaction​(transactionId); ​    }

​    ​/// @dev Allows an owner to revoke a confirmation for a transaction. ​    ​/// @param transactionId Transaction ID. ​    ​function​ revokeConfirmation​(​uint​ ​transactionId​) ​        ​public ​        ​ownerExists​(​msg​.​sender​) ​        ​confirmed​(transactionId, ​msg​.​sender​) ​        ​notExecuted​(transactionId) ​    { ​        confirmations[transactionId][​msg​.​sender​] ​=​ ​false​; ​        ​Revocation​(​msg​.​sender​, transactionId); ​    }

​    ​/// @dev Allows anyone to execute a confirmed transaction. ​    ​/// @param transactionId Transaction ID. ​    ​function​ executeTransaction​(​uint​ ​transactionId​) ​        ​public ​        ​ownerExists​(​msg​.​sender​) ​        ​confirmed​(transactionId, ​msg​.​sender​) ​        ​notExecuted​(transactionId) ​    { ​        ​if​ (​isConfirmed​(transactionId)) { ​            Transaction ​storage​ txn ​=​ transactions[transactionId]; ​            txn.executed ​=​ ​true​; ​            ​if​ (​external_call​(txn.destination, txn.value, txn.data.length, txn.data)) ​                ​Execution​(transactionId); ​            ​else​ { ​                ​ExecutionFailure​(transactionId); ​                txn.executed ​=​ ​false​; ​            } ​        } ​    }

​    ​// call has been separated into its own function in order to take advantage ​    ​// of the Solidity's code generator to produce a loop that copies tx.data into memory. ​    ​function​ external_call​(​address​ ​destination​, ​uint​ ​value​, ​uint​ ​dataLength​, ​bytes​ ​data​) ​internal​ ​returns​ (​bool​) { ​        ​bool​ result; ​        ​assembly​ { ​            ​let​ x ​:=​ ​mload​(​0x40​)   ​// "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention) ​            ​let​ d ​:=​ ​add​(data, ​32​) ​// First 32 bytes are the padded length of data, so exclude that ​            result ​:=​ ​call​( ​                ​sub​(gas, ​34710​),   ​// 34710 is the value that solidity is currently emitting ​                                   ​// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) + ​                                   ​// callNewAccountGas (25000, in case the destination address does not exist and needs creating) ​                destination, ​                value, ​                d, ​                dataLength,        ​// Size of the input (in bytes) - this is what fixes the padding problem ​                x, ​                ​0​                  ​// Output is ignored, therefore the output size is zero ​            ) ​        } ​        ​return​ result; ​    }

​    ​/// @dev Returns the confirmation status of a transaction. ​    ​/// @param transactionId Transaction ID. ​    ​/// @return Confirmation status. ​    ​function​ isConfirmed​(​uint​ ​transactionId​) ​        ​public ​        ​constant ​        ​returns​ (​bool​) ​    { ​        ​uint​ count ​=​ ​0​; ​        ​for​ (​uint​ i​=​0​; i​<​owners.length; i​++​) { ​            ​if​ (confirmations[transactionId][owners[i]]) ​                count ​+=​ ​1​; ​            ​if​ (count ​==​ required) ​                ​return​ ​true​; ​        } ​    }

​    ​/ ​      Internal functions ​     */ ​    ​/// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet. ​    ​/// @param destination Transaction target address. ​    ​/// @param value Transaction ether value. ​    ​/// @param data Transaction data payload. ​    ​/// @return Returns transaction ID. ​    ​function​ addTransaction​(​address​ ​destination​, ​uint​ ​value​, ​bytes​ ​data​) ​        ​internal ​        ​notNull​(destination) ​        ​returns​ (​uint​ ​transactionId​) ​    { ​        transactionId ​=​ transactionCount; ​        transactions[transactionId] ​=​ ​Transaction​({ ​            destination: destination, ​            value: value, ​            data: data, ​            executed: ​false ​        }); ​        transactionCount ​+=​ ​1​; ​        ​Submission​(transactionId); ​    }

​    ​/ ​      Web3 call functions ​     */ ​    ​/// @dev Returns number of confirmations of a transaction. ​    ​/// @param transactionId Transaction ID. ​    ​/// @return Number of confirmations. ​    ​function​ getConfirmationCount​(​uint​ ​transactionId​) ​        ​public ​        ​constant ​        ​returns​ (​uint​ ​count​) ​    { ​        ​for​ (​uint​ i​=​0​; i​<​owners.length; i​++​) ​            ​if​ (confirmations[transactionId][owners[i]]) ​                count ​+=​ ​1​; ​    }

​    ​/// @dev Returns total number of transactions after filers are applied. ​    ​/// @param pending Include pending transactions. ​    ​/// @param executed Include executed transactions. ​    ​/// @return Total number of transactions after filters are applied. ​    ​function​ getTransactionCount​(​bool​ ​pending​, ​bool​ ​executed​) ​        ​public ​        ​constant ​        ​returns​ (​uint​ ​count​) ​    { ​        ​for​ (​uint​ i​=​0​; i​<​transactionCount; i​++​) ​            ​if​ (   pending ​&&​ ​!​transactions[i].executed ​                ​||​ executed ​&&​ transactions[i].executed) ​                count ​+=​ ​1​; ​    }

​    ​/// @dev Returns list of owners. ​    ​/// @return List of owner addresses. ​    ​function​ getOwners​() ​        ​public ​        ​constant ​        ​returns​ (​address​[]) ​    { ​        ​return​ owners; ​    }

​    ​/// @dev Returns array with owner addresses, which confirmed transaction. ​    ​/// @param transactionId Transaction ID. ​    ​/// @return Returns array of owner addresses. ​    ​function​ getConfirmations​(​uint​ ​transactionId​) ​        ​public ​        ​constant ​        ​returns​ (​address​[] ​_confirmations​) ​    { ​        ​address​[] ​memory ​confirmationsTemp ​=​ ​new​ ​address​; ​        ​uint​ count ​=​ ​0​; ​        ​uint​ i; ​        ​for​ (i​=​0​; i​<​owners.length; i​++​) ​            ​if​ (confirmations[transactionId][owners[i]]) { ​                confirmationsTemp[count] ​=​ owners[i]; ​                count ​+=​ ​1​; ​            } ​        _confirmations ​=​ ​new​ ​address​; ​        ​for​ (i​=​0​; i​<​count; i​++​) ​            _confirmations[i] ​=​ confirmationsTemp[i]; ​    }

​    ​/// @dev Returns list of transaction IDs in defined range. ​    ​/// @param from Index start position of transaction array. ​    ​/// @param to Index end position of transaction array. ​    ​/// @param pending Include pending transactions. ​    ​/// @param executed Include executed transactions. ​    ​/// @return Returns array of transaction IDs. ​    ​function​ getTransactionIds​(​uint​ ​from​, ​uint​ ​to​, ​bool​ ​pending​, ​bool​ ​executed​) ​        ​public ​        ​constant ​        ​returns​ (​uint​[] ​_transactionIds​) ​    { ​        ​uint​[] ​memory ​transactionIdsTemp ​=​ ​new​ ​uint​; ​        ​uint​ count ​=​ ​0​; ​        ​uint​ i; ​        ​for​ (i​=​0​; i​<​transactionCount; i​++​) ​            ​if​ (   pending ​&&​ ​!​transactions[i].executed ​                ​||​ executed ​&&​ transactions[i].executed) ​            { ​                transactionIdsTemp[count] ​=​ i; ​                count ​+=​ ​1​; ​            } ​        _transactionIds ​=​ ​new​ ​uint​; ​        ​for​ (i​=​from; i​<​to; i​++​) ​            _transactionIds[i ​-​ from] ​=​ transactionIdsTemp[i]; ​    } ​}

​// File: contracts/MultiSigWalletWithDailyLimit.sol

​pragma solidity​ ​^​0.4.15​;

​/// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig. ​/// @author Stefan George - stefan.george@consensys.net ​contract​ ​MultiSigWalletWithDailyLimit​ ​is​ ​MultiSigWallet​ {

​    ​/ ​       Events ​     */ ​    ​event ​DailyLimitChange​(​uint​ ​dailyLimit​);

​    ​/ ​       Storage ​     */ ​    ​uint​ ​public​ dailyLimit; ​    ​uint​ ​public​ lastDay; ​    ​uint​ ​public​ spentToday;

​    ​/ ​      Public functions ​     */ ​    ​/// @dev Contract constructor sets initial owners, required number of confirmations and daily withdraw limit. ​    ​/// @param _owners List of initial owners. ​    ​/// @param _required Number of required confirmations. ​    ​/// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis. ​    ​function​ MultiSigWalletWithDailyLimit​(​address​[] ​_owners​, ​uint​ ​_required​, ​uint​ ​_dailyLimit​) ​        ​public ​        ​MultiSigWallet​(_owners, _required) ​    { ​        dailyLimit ​=​ _dailyLimit; ​    }

​    ​/// @dev Allows to change the daily limit. Transaction has to be sent by wallet. ​    ​/// @param _dailyLimit Amount in wei. ​    ​function​ changeDailyLimit​(​uint​ ​_dailyLimit​) ​        ​public ​        onlyWallet ​    { ​        dailyLimit ​=​ _dailyLimit; ​        ​DailyLimitChange​(_dailyLimit); ​    }

​    ​/// @dev Allows anyone to execute a confirmed transaction or ether withdraws until daily limit is reached. ​    ​/// @param transactionId Transaction ID. ​    ​function​ executeTransaction​(​uint​ ​transactionId​) ​        ​public ​        ​ownerExists​(​msg​.​sender​) ​        ​confirmed​(transactionId, ​msg​.​sender​) ​        ​notExecuted​(transactionId) ​    { ​        Transaction ​storage​ txn ​=​ transactions[transactionId]; ​        ​bool​ _confirmed ​=​ ​isConfirmed​(transactionId); ​        ​if​ (_confirmed ​||​ txn.data.length ​==​ ​0​ ​&&​ ​isUnderLimit​(txn.value)) { ​            txn.executed ​=​ ​true​; ​            ​if​ (​!​_confirmed) ​                spentToday ​+=​ txn.value; ​            ​if​ (​external_call​(txn.destination, txn.value, txn.data.length, txn.data)) ​                ​Execution​(transactionId); ​            ​else​ { ​                ​ExecutionFailure​(transactionId); ​                txn.executed ​=​ ​false​; ​                ​if​ (​!​_confirmed) ​                    spentToday ​-=​ txn.value; ​            } ​        } ​    }

​    ​/ ​      Internal functions ​     */ ​    ​/// @dev Returns if amount is within daily limit and resets spentToday after one day. ​    ​/// @param amount Amount to withdraw. ​    ​/// @return Returns if amount is under daily limit. ​    ​function​ isUnderLimit​(​uint​ ​amount​) ​        ​internal ​        ​returns​ (​bool​) ​    { ​        ​if​ (​now​ ​>​ lastDay ​+​ ​24​ ​hours​) { ​            lastDay ​=​ ​now​; ​            spentToday ​=​ ​0​; ​        } ​        ​if​ (spentToday ​+​ amount ​>​ dailyLimit ​||​ spentToday ​+​ amount ​<​ spentToday) ​            ​return​ ​false​; ​        ​return​ ​true​; ​    }

​    ​/ ​      Web3 call functions ​     */ ​    ​/// @dev Returns maximum withdraw amount. ​    ​/// @return Returns amount. ​    ​function​ calcMaxWithdraw​() ​        ​public ​        ​constant ​        ​returns​ (​uint​) ​    { ​        ​if​ (​now​ ​>​ lastDay ​+​ ​24​ ​hours​) ​            ​return​ dailyLimit; ​        ​if​ (dailyLimit ​<​ spentToday) ​            ​return​ ​0​; ​        ​return​ dailyLimit ​-​ spentToday; ​    } ​}

​// File: contracts/MultiSigWalletWithDailyLimitFactory.sol

​pragma solidity​ ​^​0.4.15​;

​/// @title Multisignature wallet factory for daily limit version - Allows creation of multisig wallet. ​/// @author Stefan George - stefan.george@consensys.net ​contract​ ​MultiSigWalletWithDailyLimitFactory​ ​is​ ​Factory​ {

​    ​/ ​      Public functions ​     */ ​    ​/// @dev Allows verified creation of multisignature wallet. ​    ​/// @param _owners List of initial owners. ​    ​/// @param _required Number of required confirmations. ​    ​/// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis. ​    ​/// @return Returns wallet address. ​    ​function​ create​(​address​[] ​_owners​, ​uint​ ​_required​, ​uint​ ​_dailyLimit​) ​        ​public ​        ​returns​ (​address​ ​wallet​) ​    { ​        wallet ​=​ ​new​ ​MultiSigWalletWithDailyLimit​(_owners, _required, _dailyLimit); ​        ​register​(wallet); ​    } ​}

bmino commented 2 years ago

hey, can you elaborate more?

bmino commented 1 year ago

closing due to inactivity