-
Notifications
You must be signed in to change notification settings - Fork 42
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
extras/axelar-token: improve error handling and add recovery paths. #814
Conversation
raulk
commented
Mar 17, 2024
- We introduce the notion of an "admin" address as the recovery operator.
- We now handle failures when parsing semi-untrusted input, and when invoking the IPC gateway. If any of those fail, we increment the allowance of the admin so they can operate the otherwise locked tokens.
- When the subnet reports a failure crediting the deposit (e.g. such as if the recipient was a smart contract / actor that reverted), we increment the allowance of the admin also. This is more failsafe and easier to operate than crediting the funds to the recipient on the L1 (who wouldn't be able to rescue them if it was a smart contract, unless it could manage to deploy itself onto the same address it had in the subnet, plausible if it used Deploy3).
- As an ultimate backstop, we introduce a method so that the operator can increase its allowance on any token. This should only be used iff something unexpected failed, like the error handling paths themselves.
1. We introduce the notion of an "admin" address as the recovery operator. 2. We now handle failures when parsing semi-untrusted input, and when invoking the IPC gateway. If any of those fail, we increment the allowance of the admin so they can operate the otherwise locked tokens. 3. When the subnet reports a failure crediting the deposit (e.g. such as if the recipient was a smart contract / actor that reverted), we increment the allowance of the admin also. This is more failsafe and easier to operate than crediting the funds to the recipient on the L1 (who wouldn't be able to rescue them if it was a smart contract, unless it could manage to deploy itself onto the same address it had in the subnet, plausible if it used Deploy3). 4. As an ultimate backstop, we introduce a method so that the operator can increase its allowance on any token. This should only be used iff something unexpected failed, like the error handling paths themselves.
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 the changes are productive and aim to properly increase security and create recovery against potential issues. I would love to see a test for the admin token recovery flow, but on face value it is simple and appears to be correct
IERC20 token = IERC20(tokenAddr); | ||
require(token.balanceOf(address(this)) >= amount, "insufficient balance"); | ||
|
||
// Authorize the IPC gateway to spend these tokens on our behalf. | ||
token.approve(address(_ipcGateway), amount); | ||
token.safeIncreaseAllowance(address(_ipcGateway), 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 wasn't aware of safeIncreaseAllowance - it is helpful!
|
||
// Emit a FundingFailed event; we can't associate a specific subnet or recipient since parsing may have failed. | ||
SubnetID memory nilSubnet; | ||
emit FundingFailed(nilSubnet, address(0), 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.
Can we want to emit msg.sender or tx.origin here? Or will that tend to be not helpful information like "gateway" or "ipc subnet" would be the callers?
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 refactored the solution a bit, and now we're able to pass actual data here.
// increase the recovery allowances of the admin address. | ||
function adminTokenIncreaseAllowance(address token, uint256 amount) external { | ||
require(msg.sender == _admin, "unauthorized"); | ||
IERC20(token).safeIncreaseAllowance(_admin, 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.
If this is our back pocket trump card to unroll any errors, can we get a simple test for the recovery?
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.
Done here: f0a035a
c3703ea
to
cdf5bd1
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.
looks good