Skip to content

Commit

Permalink
Refactor approveAndCall logic into the BaseTransfer module
Browse files Browse the repository at this point in the history
  • Loading branch information
elenadimitrova committed Apr 3, 2020
1 parent 52df688 commit 3d51aab
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 34 deletions.
33 changes: 1 addition & 32 deletions contracts/modules/ApprovedTransfer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,6 @@ import "../../lib/other/ERC20.sol";
contract ApprovedTransfer is BaseModule, RelayerModuleV2, BaseTransfer {

bytes32 constant NAME = "ApprovedTransfer";
event ApprovedAndCalledContract(
address indexed wallet,
address indexed to,
address spender,
address indexed token,
uint256 amountApproved,
uint256 amountSpent,
bytes data
);

constructor(ModuleRegistry _registry, GuardianStorage _guardianStorage) BaseModule(_registry, _guardianStorage, NAME) public {

Expand Down Expand Up @@ -110,29 +101,7 @@ contract ApprovedTransfer is BaseModule, RelayerModuleV2, BaseTransfer {
onlyWhenUnlocked(_wallet)
{
require(!_wallet.authorised(_contract) && _contract != address(_wallet), "AT: Forbidden contract");
uint256 currentAllowance = ERC20(_token).allowance(address(_wallet), _spender);

// Approve the desired amount
bytes memory methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, _amount);
invokeWallet(address(_wallet), _token, 0, methodData);

invokeWallet(address(_wallet), _contract, 0, _data);

uint256 unusedAllowance = ERC20(_token).allowance(address(_wallet), _spender);
uint256 usedAllowance = SafeMath.sub(_amount, unusedAllowance);

// Restore the original allowance amount
methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, currentAllowance);
invokeWallet(address(_wallet), _token, 0, methodData);

emit ApprovedAndCalledContract(
address(_wallet),
_contract,
_spender,
_token,
_amount,
usedAllowance,
_data);
doApproveTokenAndCallContract(_wallet, _token, _spender, _amount, _contract, _data);
}

// *************** Implementation of RelayerModule methods ********************* //
Expand Down
54 changes: 53 additions & 1 deletion contracts/modules/common/BaseTransfer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ contract BaseTransfer is BaseModule {
event Transfer(address indexed wallet, address indexed token, uint256 indexed amount, address to, bytes data);
event Approved(address indexed wallet, address indexed token, uint256 amount, address spender);
event CalledContract(address indexed wallet, address indexed to, uint256 amount, bytes data);

event ApprovedAndCalledContract(
address indexed wallet,
address indexed to,
address spender,
address indexed token,
uint256 amountApproved,
uint256 amountSpent,
bytes data
);
// *************** Internal Functions ********************* //

/**
Expand Down Expand Up @@ -77,4 +85,48 @@ contract BaseTransfer is BaseModule {
invokeWallet(address(_wallet), _contract, _value, _data);
emit CalledContract(address(_wallet), _contract, _value, _data);
}

/**
* @dev Helper method to call an external contract.
* @param _wallet The target wallet.
* @param _token The ERC20 address.
* @param _spender The spender address.
* @param _amount The amount of tokens to transfer.
* @param _contract The contract address.
* @param _data The method data.
*/
function doApproveTokenAndCallContract(
BaseWallet _wallet,
address _token,
address _spender,
int256 _amount,
address _contract,
bytes memory _data
)
internal
{
uint256 currentAllowance = ERC20(_token).allowance(address(_wallet), _spender);

// Approve the desired amount
bytes memory methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, _amount);
invokeWallet(address(_wallet), _token, 0, methodData);

invokeWallet(address(_wallet), _contract, 0, _data);

uint256 unusedAllowance = ERC20(_token).allowance(address(_wallet), _spender);
uint256 usedAllowance = SafeMath.sub(_amount, unusedAllowance);

// Restore the original allowance amount
methodData = abi.encodeWithSignature("approve(address,uint256)", _spender, currentAllowance);
invokeWallet(address(_wallet), _token, 0, methodData);

emit ApprovedAndCalledContract(
address(_wallet),
_contract,
_spender,
_token,
_amount,
usedAllowance,
_data);
}
}
3 changes: 2 additions & 1 deletion test/approvedTransfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ describe("Approved Transfer", function () {
const allowanceBefore = await erc20.allowance(wallet.contractAddress, consumer);
const balanceBefore = await erc20.balanceOf(contract.contractAddress);

dataToTransfer = contract.contract.interface.functions.setStateAndPayTokenWithConsumer.encode([2, erc20.contractAddress, amountToApprove]);
const dataToTransfer = contract.contract.interface.functions
.setStateAndPayTokenWithConsumer.encode([2, erc20.contractAddress, amountToApprove]);
await manager.relay(approvedTransfer, "approveTokenAndCallContract",
[wallet.contractAddress, erc20.contractAddress, consumer, amountToApprove, contract.contractAddress, dataToTransfer],
wallet, [owner, ...sortWalletByAddress([guardian1, guardian2])]);
Expand Down

0 comments on commit 3d51aab

Please sign in to comment.