-
Notifications
You must be signed in to change notification settings - Fork 21
Added upgradable contraintLimits #798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
orenyodfat
merged 31 commits into
daostack:master
from
nicoelzer:schemeConstraintUpgradable
Oct 16, 2020
Merged
Changes from 17 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
2a87697
simplify contract
685675e
tests
6b91201
test approval
feae9ee
check spender is white listed
1a6cd03
clean
e06fe11
poc
8872446
Add SchemeConstraints interface
9c9b4ab
add eth constraint as an example for DxDaoSchemeConstraint
e7cb197
+
519f7cb
more ..
221721f
fix dxdao constraints
8917c30
check schemeConstraint exist
aad9d93
+ comments
912657e
Merge branch 'master' into schemeconstraint
orenyodfat 8a0bd6b
coverage
09c040e
Added upgradable contraintLimits
nicoelzer 0231a5f
updated genericschmemulticall tests
nicoelzer d6809a2
Updated DXdaoSchemeConstraints
nicoelzer ad54756
Added contraint events and smaller updates
nicoelzer 990ca26
Added additional tests for DxDaoSchemeConstraints
nicoelzer bd5a72b
rebase from arc/master
nicoelzer aad8929
Updated DxDaoSchemeContraints events & general cleanup
nicoelzer 1b319f6
solhint cleanup
nicoelzer 20469c7
Merge branch 'master' into schemeConstraintUpgradable
nicoelzer 32c8403
cleanup
nicoelzer 9aa64d2
Merge branch 'schemeConstraintUpgradable' of https://github.com/nicoe…
nicoelzer 58b64b8
Fixed test issues
nicoelzer 75a38d1
updated DxDaoSchemeConstraints.sol
nicoelzer d1d85ce
only genericSchemeMultiCall can call isAllowToCall
924f713
comments
3f6c82a
Added additional test for GenericSchemeMultiCall
nicoelzer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
pragma solidity 0.5.17; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "./SchemeConstraints.sol"; | ||
|
||
|
||
contract DxDaoSchemeConstraints is SchemeConstraints { | ||
using SafeMath for uint256; | ||
|
||
address public avatar; | ||
uint256 public initialTimestamp; | ||
uint256 public periodSize; | ||
uint256 public periodLimitWei; | ||
|
||
mapping(uint256=>uint256) public periodSpendingTokens; | ||
mapping(address=>uint256) public periodLimitToken; | ||
mapping (uint256 => mapping(address => uint256)) public periodSpendingToken; | ||
mapping(uint256=>uint256) public periodSpendingWei; | ||
mapping(address=>bool) public contractsWhiteListMap; | ||
bytes4 private constant APPROVE_SIGNATURE = 0x095ea7b3;//approve(address,uint256) | ||
|
||
/* @dev initialize | ||
* @param avatar the DAOs avatar address | ||
* @param _periodSize the time period to limit the tokens and eth spending | ||
* @param _periodLimitWei the limit of eth which can be sent per period | ||
* @param _periodLimitTokensAddresses tokens to limit | ||
* @param _periodLimitTokensAmounts the limit of token which can be sent per period | ||
* @param _contractsWhiteList the contracts the scheme is allowed to interact with | ||
*/ | ||
function initialize( | ||
address _avatar, | ||
uint256 _periodSize, | ||
uint256 _periodLimitWei, | ||
address[] calldata _periodLimitTokensAddresses, | ||
uint256[] calldata _periodLimitTokensAmounts, | ||
address[] calldata _contractsWhiteList | ||
) | ||
external { | ||
require(initialTimestamp == 0, "cannot initialize twice"); | ||
require(_periodSize > 0, "preriod size should be greater than 0"); | ||
require(_periodLimitTokensAddresses.length == _periodLimitTokensAmounts.length, | ||
"invalid length _periodLimitTokensAddresses"); | ||
periodSize = _periodSize; | ||
periodLimitWei = _periodLimitWei; | ||
avatar = _avatar; | ||
// solhint-disable-next-line not-rely-on-time | ||
initialTimestamp = block.timestamp; | ||
for (uint i = 0; i < _contractsWhiteList.length; i++) { | ||
contractsWhiteListMap[_contractsWhiteList[i]] = true; | ||
} | ||
for (uint i = 0; i < _periodLimitTokensAmounts.length; i++) { | ||
periodLimitToken[_periodLimitTokensAddresses[i]] = _periodLimitTokensAmounts[i]; | ||
} | ||
contractsWhiteList = _contractsWhiteList; | ||
} | ||
|
||
/* | ||
* @dev updateContractWhitelist used to let the DAO update whitelisted contracts. | ||
* @param _contractsAddresses - The contract that should be update | ||
* @param _contractsWhitelisted – true adds a contract to the whitelist, false removes it. | ||
*/ | ||
function updateContractWhitelist( | ||
address[] calldata _contractsAddresses, | ||
bool[] calldata _contractsWhitelisted | ||
) | ||
external { | ||
require(msg.sender == avatar, "caller must be avatar"); | ||
require(_contractsAddresses.length == _contractsWhitelisted.length, | ||
"invalid length _periodLimitTokensAddresses"); | ||
for (uint i = 0; i < _contractsAddresses.length; i++) { | ||
contractsWhiteListMap[_contractsAddresses[i]] = _contractsWhitelisted[i]; | ||
} | ||
} | ||
|
||
/* | ||
* @dev updatePeriodLimitTokens lets the dao update limits to token limits. | ||
* @param _tokensAddresses - The token that should be updated | ||
nicoelzer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @param _tokensPeriodLimits – The amount that will be set as a spending limit | ||
*/ | ||
function updatePeriodLimitTokens( | ||
address[] calldata _tokensAddresses, | ||
uint256[] calldata _tokensPeriodLimits | ||
) | ||
external { | ||
require(msg.sender == avatar, "caller must be avatar"); | ||
require(_tokensAddresses.length == _tokensPeriodLimits.length, | ||
"invalid length _tokensPeriodLimits"); | ||
for (uint i = 0; i < _tokensAddresses.length; i++) { | ||
periodLimitToken[_tokensAddresses[i]] = _tokensPeriodLimits[i]; | ||
} | ||
} | ||
|
||
/* | ||
* @dev updatePeriodLimitWei lets the dao update limits to ETH spending limit. | ||
* @param _periodLimitWei - The new spending limit in WEI that should be set. | ||
*/ | ||
function updatePeriodLimitWei(uint256 _periodLimitWei) external { | ||
nicoelzer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
require(msg.sender == avatar, "caller must be avatar"); | ||
periodLimitWei = _periodLimitWei; | ||
} | ||
|
||
/* | ||
* @dev isAllowedToCall should be called upon a proposal execution. | ||
* - check that the total spending of tokens within a 'periodSize' does not exceed the periodLimit per token | ||
* - check that the total sending of eth within a 'periodSize' does not exceed the periodLimit | ||
* @param _contractsToCall the contracts to be called | ||
* @param _callsData - The abi encode data for the calls | ||
* @param _values value(ETH) to transfer with the calls | ||
* @param _avatar avatar | ||
* @return bool value true-allowed false not allowed | ||
*/ | ||
function isAllowedToCall( | ||
address[] calldata _contractsToCall, | ||
bytes[] calldata _callsData, | ||
uint256[] calldata _values, | ||
Avatar | ||
) | ||
external | ||
returns(bool) | ||
{ | ||
|
||
uint256 observervationIndex = observationIndex(); | ||
uint256 totalPeriodSpendingInWei; | ||
for (uint i = 0; i < _contractsToCall.length; i++) { | ||
// constraint eth transfer | ||
totalPeriodSpendingInWei = totalPeriodSpendingInWei.add(_values[i]); | ||
bytes memory callData = _callsData[i]; | ||
// constraint approve calls | ||
if (callData[0] == APPROVE_SIGNATURE[0] && | ||
callData[1] == APPROVE_SIGNATURE[1] && | ||
callData[2] == APPROVE_SIGNATURE[2] && | ||
callData[3] == APPROVE_SIGNATURE[3]) { | ||
uint256 amount; | ||
address contractToCall = _contractsToCall[i]; | ||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
amount := mload(add(callData, 68)) | ||
nicoelzer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
periodSpendingToken[observervationIndex][contractToCall] = | ||
periodSpendingToken[observervationIndex][contractToCall].add(amount); | ||
require( | ||
periodSpendingToken[observervationIndex][contractToCall] <= periodLimitToken[contractToCall], | ||
"periodSpendingTokensExceeded"); | ||
} | ||
|
||
} | ||
periodSpendingWei[observervationIndex] = | ||
periodSpendingWei[observervationIndex].add(totalPeriodSpendingInWei); | ||
require(periodSpendingWei[observervationIndex] <= periodLimitWei, "periodSpendingWeiExceeded"); | ||
return true; | ||
} | ||
|
||
/* | ||
* @dev isAllowedToPropose should be called upon a proposal submition. | ||
* allow only whitelisted target contracts or 'approve' calls which the 'spender' is whitelisted | ||
* @param _contractsToCall the contracts to be called | ||
* @param _callsData - The abi encode data for the calls | ||
* @param _values value(ETH) to transfer with the calls | ||
* @param _avatar avatar | ||
* @return bool value true-allowed false not allowed | ||
*/ | ||
function isAllowedToPropose( | ||
address[] calldata _contractsToCall, | ||
bytes[] calldata _callsData, | ||
uint256[] calldata, | ||
Avatar) | ||
external | ||
returns(bool) | ||
{ | ||
for (uint i = 0; i < _contractsToCall.length; i++) { | ||
if (!contractsWhiteListMap[_contractsToCall[i]]) { | ||
address spender; | ||
bytes memory callData = _callsData[i]; | ||
require( | ||
callData[0] == APPROVE_SIGNATURE[0] && | ||
callData[1] == APPROVE_SIGNATURE[1] && | ||
callData[2] == APPROVE_SIGNATURE[2] && | ||
callData[3] == APPROVE_SIGNATURE[3], | ||
"allow only approve call for none whitelistedContracts"); | ||
//in solidity > 6 this can be replaced by: | ||
//(spender,) = abi.descode(callData[4:], (address, uint)); | ||
// see https://github.com/ethereum/solidity/issues/9439 | ||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
spender := mload(add(callData, 36)) | ||
} | ||
require(contractsWhiteListMap[spender], "spender contract not whitelisted"); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
function observationIndex() public view returns (uint256) { | ||
// solhint-disable-next-line not-rely-on-time | ||
return uint8((block.timestamp - initialTimestamp) / periodSize); | ||
} | ||
|
||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
pragma solidity 0.5.17; | ||
pragma experimental ABIEncoderV2; | ||
import "../controller/Avatar.sol"; | ||
|
||
|
||
contract SchemeConstraints { | ||
|
||
address[] public contractsWhiteList; | ||
|
||
/* | ||
* @dev isAllowedToCall should be called upon a proposal execution. | ||
* @param _contractsToCall the contracts to be called | ||
* @param _callsData - The abi encode data for the calls | ||
* @param _values value(ETH) to transfer with the calls | ||
* @param _avatar avatar | ||
* @return bool value true-allowed false not allowed | ||
*/ | ||
function isAllowedToCall( | ||
address[] calldata _contractsToCall, | ||
bytes[] calldata _callsData, | ||
uint256[] calldata _values, | ||
Avatar _avatar) | ||
external returns(bool); | ||
|
||
/* | ||
* @dev isAllowedToPropose should be called upon a proposal submition. | ||
* @param _contractsToCall the contracts to be called | ||
* @param _callsData - The abi encode data for the calls | ||
* @param _values value(ETH) to transfer with the calls | ||
* @param _avatar avatar | ||
* @return bool value true-allowed false not allowed | ||
*/ | ||
function isAllowedToPropose( | ||
address[] calldata _contractsToCall, | ||
bytes[] calldata _callsData, | ||
uint256[] calldata _values, | ||
Avatar _avatar) | ||
external returns(bool); | ||
|
||
function getContractsWhiteList() external view returns(address[] memory) { | ||
return contractsWhiteList; | ||
} | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.