Skip to content
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

Merged
merged 4 commits into from
Mar 19, 2024

Conversation

raulk
Copy link
Contributor

@raulk raulk commented Mar 17, 2024

  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.

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.
@raulk raulk requested a review from snissn March 17, 2024 20:33
@raulk raulk added the Fluence label Mar 18, 2024
Copy link
Contributor

@snissn snissn left a 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);
Copy link
Contributor

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);
Copy link
Contributor

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?

Copy link
Contributor Author

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);
}
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done here: f0a035a

@raulk raulk force-pushed the raulk/axelar-failsafe-admin branch from c3703ea to cdf5bd1 Compare March 19, 2024 19:19
Copy link

@crystalbit crystalbit left a comment

Choose a reason for hiding this comment

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

looks good

@raulk raulk merged commit c49b0e7 into main Mar 19, 2024
14 checks passed
@raulk raulk deleted the raulk/axelar-failsafe-admin branch March 19, 2024 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants