-
Notifications
You must be signed in to change notification settings - Fork 215
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
Enhance approveAndCall logic #84
Conversation
3d51aab
to
2416398
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add the deployment of the new TransferManager
in 7_upgrade_1_6.js
.
uint256 currentAllowance = ERC20(_token).allowance(address(_wallet), _spender); | ||
|
||
// Approve the desired amount | ||
bytes memory methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, _amount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should here approve currentAllowance + _amount
so if unusedAllowance == currentAllowance
after the contract call (which should be the majority of the cases) then we don't need to make the call on L121 and we save gas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with that is that the new allowance amount left can be different to the original allowance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we would be allowing that TX to use your existing allowance, so should set explicit amount before the call, make the call, and then reset to old allowance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we error if the called contract consumes more than they approved in this call (spending additionally from their original approved amount)?
uint256 amountApproved, | ||
uint256 amountSpent, | ||
bytes data | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should index wallet
token
and amountSpent
to mirror what we index in Transfer
? I suspect that it is the main information the clients are interested in. Maybe check with @th3m477 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think uint256 values need to be indexed generally, makes no client difference here as it's a new event.
Addresses make more sense as we are more likely to do exploratory network analysis in the future, or quick filters (i.e. "show me all the transfers I made to X address"), so more of a case for spender
, but up to you @juniset @elenadimitrova
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we can only have up to 3 indexed arguments per event so leaving as is.
e002379
to
cd877b1
Compare
|
||
// Restore the original allowance amount. | ||
methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, existingAllowance); | ||
invokeWallet(address(_wallet), _token, 0, methodData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is an IF missing if we want to save some gas and it should be:
if (unusedAllowance != existingAllowance) {
// Restore the original allowance amount.
methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, existingAllowance);
invokeWallet(address(_wallet), _token, 0, methodData);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally omitted it as we won't pay for storage updates when the value doesn't change. So implicitly this is enforced anyway while keeping the code simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I believe there will still be quite some gas consumed by invoking the wallet: internal call to the wallet, then delegatecall to the wallet implementation, then checking that the calling address is an authorised module, then calling the token contract which itself need to do a few check before updating the memory slot (even if this last step is free).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's around 12470
gas which is approx 1 cent worth at current prices. I can't tell whether the complexity outweighs the advantage but I'll add it.
deployment/7_upgrade_1_6.js
Outdated
config.settings.securityPeriod || 0, | ||
config.settings.securityWindow || 0, | ||
config.settings.defaultLimit || "1000000000000000000", | ||
["test", "staging", "prod"].includes(network) ? config.modules.TokenTransfer : "0x0000000000000000000000000000000000000000", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be config.modules.TransferManager
and not config.modules.TokenTransfer
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But config.modules.TokenTransfer
is the address of the old config.modules.TransferManager
no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe when upgrading the TransferManager we should copy its old value here though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the address of the first version of the TransferManager, yes. But here we are going from the second version (config.modules.TransferManager
) to the third one. So the new TransferManager needs to read the state of a wallet's limit from the second version which is config.modules.TransferManager
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we update the config.modules.TransferManager
address to the new one in the same script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, removed TokenTransfer
in favour of using TransferManager
value prior to upgrade updates.
|
||
const utils = require("../utils/utilities.js"); | ||
|
||
const TARGET_VERSION = "1.6.0"; | ||
const MODULES_TO_ENABLE = ["ApprovedTransfer", "RecoveryManager", "MakerV2Manager"]; | ||
const MODULES_TO_ENABLE = ["ApprovedTransfer", "RecoveryManager", "MakerV2Manager", "TransferManager"]; | ||
const MODULES_TO_DISABLE = ["UniswapManager"]; | ||
|
||
const BACKWARD_COMPATIBILITY = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we say we would set BACKWARD_COMPATIBILITY
to 1
and remove the part of the script where we create a LegacyUpgrader
? Or are we addressing this in a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a separate PR for it #91 as I wanted to double check the clients can support the upgrade through 1.4 -> 1.6
Which restores the original approved amount after an approveAndCall and emits a new dedicated event
Rename contract instances to match the contract types they represent
1bfa7b1
to
8523af9
Compare
…ddress prior to upgrades, otherwise use 0x0
In the current implementation of
approveTokenAndCallContract
, the amount of tokens approved overwrites any existing amount of the same token and spender. Here we add logic to restore the original approved amount after theapproveTokenAndCallContract
call in both (ApprovedTransfer
andTransferManager
) and emit a new dedicated event with the following definition:This PR also enables a different contract address for the approved spender and the called contract for
TransferManager
module, analogous to behaviour already implemented forApprovedTransfer
in #73Also I needed
SafeMath
in theBaseTransfer
contract so pushing it there meant this was provisioned to bothApprovedTransfer
andTransferManager
.We also decommission the
config.modules.TokenTransfer
config entry.