Skip to content

Conversation

@alikhabazian
Copy link
Collaborator

In this part has been tried to add another erc20 tokens

Copy link
Member

@mehrdadmms mehrdadmms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the suggestions and then test. I didn't test the code just added the suggestions.

Comment on lines 32 to 46
/// @notice Initializes the contract.
/// @param _dao The associated DAO.
/// @param _hatId The id of the hat.
function initialize(IDAO _dao, uint256 _hatId, uint256 _spendingLimitETH) external initializer {
function initialize(IDAO _dao, uint256 _hatId,address[] memory _token ,uint256[] memory _spendingLimit) external initializer {
__PluginCloneable_init(_dao);
hatId = _hatId;
// TODO get this from environment per network (this is goerli)
hatsProtocolInstance = IHats(0x3bc1A0Ad72417f2d411118085256fC53CBdDd137);
spendingLimitETH = _spendingLimitETH;
require(_token.length==_spendingLimit.length,"Length of token address and spendingLimit array is not equal");
// spendingLimit = _spendingLimit;
for (uint j=0; j < _token.length; j+=1) {
spendingLimit[_token[j]]=_spendingLimit[j];
}
availableTokens=_token;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an array of objects instead of 2 arrays?

Suggested change
/// @notice Initializes the contract.
/// @param _dao The associated DAO.
/// @param _hatId The id of the hat.
function initialize(IDAO _dao, uint256 _hatId, uint256 _spendingLimitETH) external initializer {
function initialize(IDAO _dao, uint256 _hatId,address[] memory _token ,uint256[] memory _spendingLimit) external initializer {
__PluginCloneable_init(_dao);
hatId = _hatId;
// TODO get this from environment per network (this is goerli)
hatsProtocolInstance = IHats(0x3bc1A0Ad72417f2d411118085256fC53CBdDd137);
spendingLimitETH = _spendingLimitETH;
require(_token.length==_spendingLimit.length,"Length of token address and spendingLimit array is not equal");
// spendingLimit = _spendingLimit;
for (uint j=0; j < _token.length; j+=1) {
spendingLimit[_token[j]]=_spendingLimit[j];
}
availableTokens=_token;
}
struct Budget {
address token;
uint256 spendingLimit;
}
/// @notice Initializes the contract.
/// @param _dao The associated DAO.
/// @param _hatId The id of the hat.
/// @param _budget An array of Budgest struct which is an object consisted of token address and spending amount.
function initialize(IDAO _dao, uint256 _hatId, Budget[] calldata _budget) external initializer {
__PluginCloneable_init(_dao);
hatId = _hatId;
// TODO get this from environment per network (this is goerli)
hatsProtocolInstance = IHats(0x3bc1A0Ad72417f2d411118085256fC53CBdDd137);
for (uint j=0; j < _budget.length; j+=1) {
spendingLimit[_budget[j].token] = _budget[j].spendingLimit;
availableTokens = _budget[j].token
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it manually

Comment on lines 118 to 126
/// @notice Executes actions in the associated DAO.
/// @param _actions The actions to be executed by the DAO.
/// @param _myActions The actions to be executed by the DAO.
function execute(
IDAO.Action[] calldata _actions
MyAction[] calldata _myActions
) external {
require(hatsProtocolInstance.isWearerOfHat(msg.sender, hatId), "Sender is not wearer of the hat");
hasRemainingBudget(_actions);
dao().execute({_callId: 0x0, _actions: _actions, _allowFailureMap: 0});
IDAO.Action [] memory idaoAction = hasRemainingBudget(_myActions);
dao().execute({_callId: 0x0, _actions: idaoAction, _allowFailureMap: 0});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// @notice Executes actions in the associated DAO.
/// @param _actions The actions to be executed by the DAO.
/// @param _myActions The actions to be executed by the DAO.
function execute(
IDAO.Action[] calldata _actions
MyAction[] calldata _myActions
) external {
require(hatsProtocolInstance.isWearerOfHat(msg.sender, hatId), "Sender is not wearer of the hat");
hasRemainingBudget(_actions);
dao().execute({_callId: 0x0, _actions: _actions, _allowFailureMap: 0});
IDAO.Action [] memory idaoAction = hasRemainingBudget(_myActions);
dao().execute({_callId: 0x0, _actions: idaoAction, _allowFailureMap: 0});
}
/// @notice Executes actions in the associated DAO.
/// @param _workingCapitalActions The actions to be executed by the DAO.
function execute(
WorkingCapitalAction[] calldata _workingCapitalActions
) external {
require(hatsProtocolInstance.isWearerOfHat(msg.sender, hatId), "Sender is not wearer of the hat");
IDAO.Action [] memory iDAOAction = hasRemainingBudget(_workingCapitalActions);
dao().execute({_callId: 0x0, _actions: iDAOAction, _allowFailureMap: 0});
}

Comment on lines 61 to 115
/// @notice Checking that can user withdraw this amount
/// @param _actions actions that would be checked
function hasRemainingBudget(IDAO.Action[] calldata _actions) internal {
/// @return generatedDAOActions IDAO.Action generated for use in execute
function hasRemainingBudget(MyAction[] calldata _actions) internal returns(IDAO.Action[] memory generatedDAOActions){
uint _currentMonth = BokkyPooBahsDateTimeLibrary.getMonth(block.timestamp);
uint _currentYear = BokkyPooBahsDateTimeLibrary.getYear(block.timestamp);
uint j=0;
for (; j < _actions.length; j+=1) { //for loop example
generatedDAOActions = new IDAO.Action[](_actions.length);
for (uint j=0; j < _actions.length; j+=1) {
address _to;
uint256 _value;
bytes memory _data;
address _token;
if(_actions[j].ERC20 == address(0)){
_to=_actions[j].to;
_value=_actions[j].value;
_data= new bytes(0);
_token=address(0);
require(isTokenAvailable(address(0)),"It is not available token in this plugin");

}
else{
_to=_actions[j].ERC20;
_value=0;
bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", _actions[j].to, _actions[j].value);
_data= data;
_token=_actions[j].ERC20;
require(isTokenAvailable(_actions[j].ERC20),"It is not available token in this plugin");

}
// if we are on the month that we were
if(_currentMonth==currentMonth && _currentYear==currentYear){
require(
remainingBudget>=_actions[j].value,
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget-=_actions[j].value;
remainingBudget[_token] -=_actions[j].value;
}
// if we are on another month
else{
currentYear = _currentYear;
currentMonth = _currentMonth;
remainingBudget=spendingLimitETH;
for (uint j=0; j < availableTokens.length; j+=1) {
remainingBudget[availableTokens[j]]=spendingLimit[availableTokens[j]];
}
require(
remainingBudget>=_actions[j].value,
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget-=_actions[j].value;
remainingBudget[_token]-=_actions[j].value;
}

generatedDAOActions[j]=IDAO.Action(_to, _value, _data);

}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// @notice Checking that can user withdraw this amount
/// @param _actions actions that would be checked
function hasRemainingBudget(IDAO.Action[] calldata _actions) internal {
/// @return generatedDAOActions IDAO.Action generated for use in execute
function hasRemainingBudget(MyAction[] calldata _actions) internal returns(IDAO.Action[] memory generatedDAOActions){
uint _currentMonth = BokkyPooBahsDateTimeLibrary.getMonth(block.timestamp);
uint _currentYear = BokkyPooBahsDateTimeLibrary.getYear(block.timestamp);
uint j=0;
for (; j < _actions.length; j+=1) { //for loop example
generatedDAOActions = new IDAO.Action[](_actions.length);
for (uint j=0; j < _actions.length; j+=1) {
address _to;
uint256 _value;
bytes memory _data;
address _token;
if(_actions[j].ERC20 == address(0)){
_to=_actions[j].to;
_value=_actions[j].value;
_data= new bytes(0);
_token=address(0);
require(isTokenAvailable(address(0)),"It is not available token in this plugin");
}
else{
_to=_actions[j].ERC20;
_value=0;
bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", _actions[j].to, _actions[j].value);
_data= data;
_token=_actions[j].ERC20;
require(isTokenAvailable(_actions[j].ERC20),"It is not available token in this plugin");
}
// if we are on the month that we were
if(_currentMonth==currentMonth && _currentYear==currentYear){
require(
remainingBudget>=_actions[j].value,
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget-=_actions[j].value;
remainingBudget[_token] -=_actions[j].value;
}
// if we are on another month
else{
currentYear = _currentYear;
currentMonth = _currentMonth;
remainingBudget=spendingLimitETH;
for (uint j=0; j < availableTokens.length; j+=1) {
remainingBudget[availableTokens[j]]=spendingLimit[availableTokens[j]];
}
require(
remainingBudget>=_actions[j].value,
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget-=_actions[j].value;
remainingBudget[_token]-=_actions[j].value;
}
generatedDAOActions[j]=IDAO.Action(_to, _value, _data);
}
}
/// @notice Checking that can user withdraw this amount
/// @param _actions actions that would be checked
/// @return generatedDAOActions IDAO.Action generated for use in execute
function hasRemainingBudget(WorkingCapitalAction[] calldata _actions) internal returns(IDAO.Action[] memory generatedDAOActions){
uint _currentMonth = BokkyPooBahsDateTimeLibrary.getMonth(block.timestamp);
uint _currentYear = BokkyPooBahsDateTimeLibrary.getYear(block.timestamp);
generatedDAOActions = new IDAO.Action[](_actions.length);
for (uint j=0; j < _actions.length; j+=1) {
address _to;
uint256 _value;
bytes memory _data;
address _token;
if(_actions[j].erc20Address == address(0)){
_to=_actions[j].to;
_value=_actions[j].value;
_data= new bytes(0);
_token=address(0);
require(isTokenAvailable(address(0)),"It is not available token in this plugin");
}
else{
_to=_actions[j].erc20Address;
_value=0;
bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", _actions[j].to, _actions[j].value);
_data= data;
_token=_actions[j].erc20Address;
require(isTokenAvailable(_actions[j].erc20Address),"It is not available token in this plugin");
}
// if we are on the month that we were
if(_currentMonth==currentMonth && _currentYear==currentYear){
require(
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget[_token] -=_actions[j].value;
}
// if we are on another month
else{
currentYear = _currentYear;
currentMonth = _currentMonth;
for (uint j=0; j < availableTokens.length; j+=1) {
remainingBudget[availableTokens[j]]=spendingLimit[availableTokens[j]];
}
require(
remainingBudget[_token]>=_actions[j].value,
string.concat("In ",Strings.toString(j)," action you want to spend more than your limit monthly")
);
remainingBudget[_token]-=_actions[j].value;
}
generatedDAOActions[j]=IDAO.Action(_to, _value, _data);
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it manually

Comment on lines 49 to 58
/// @notice Check that the given token has allowance
/// @param _token check that given token has allowance
function isTokenAvailable(address _token) internal view returns (bool) {
for (uint256 i = 0; i < availableTokens.length; i++) {
if (availableTokens[i] == _token) {
return true;
}
}
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of using for you can use hashtable.
Instead of using availableTokens array just use spendingLimit[token].
if spendingLimit[token] was 0 or undefined it means that the token is not available.

Copy link
Member

@mehrdadmms mehrdadmms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the suggestions and then test. I didn't test the code just added the suggestions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants