PseudoCode for self-custodial Polygon swaps made via the deversifi UI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity >=0.4.22 <0.9.0; | |
import "../node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | |
import "./libraries/TransferHelper.sol"; | |
/** | |
* Deversifi polygon contract for holding user's balances self-custodially while facilitating quick and cheap swaps using only signatures | |
*/ | |
contract DVFPolygonSwapContract is OwnableUpgradeable { | |
mapping(address => bool) public authorized; | |
mapping(string => bool) public processedTradeIds; | |
modifier _isAuthorized() { | |
require( | |
authorized[msg.sender], | |
"UNAUTHORIZED" | |
); | |
_; | |
} | |
modifier _validateTradeId(string calldata tradeId) { | |
require( | |
bytes(tradeId).length > 0, | |
"Trade ID is required" | |
); | |
require( | |
!processedTradeIds[tradeId], | |
"Trade ID Already processed" | |
); | |
_; | |
} | |
event BridgedTrade(address indexed user, address indexed purchasedtoken, uint256 purchasedamount, address indexed soldToken, uint256 soldAmount); | |
function initialize() public initializer { | |
__Ownable_init(); | |
authorized[_msgSender()] = true; | |
} | |
/** | |
* @dev Make a swap on behalf of user with their signature on Polygon with Quickswap | |
* NOTE: Validates that the user signed permission for this in the deversifi UI | |
* NOTE: After a successful swap, update the user's record on this contract of their new balance, so they could withdraw new balance if they chose | |
*/ | |
function makeSwapForUser( | |
address _trader, | |
address _tokenFrom, | |
uint _amountFrom, | |
address _tokenTo, | |
uint _amountTo, | |
uint _signatureValidUntilBlock, | |
uint8 v, | |
bytes32 r, | |
bytes32 s, | |
string calldata tradeId | |
) external _isAuthorized _validateTradeId(tradeId) { | |
require(getBalance(_tokenFrom, msg.sender)) >= _amountFrom); | |
require(_signatureValidUntilBlock > block.number); | |
require(isValidSignature(keccak256(msg.sender, _tokenFrom, ...etc, ...etc), v, r, s)); | |
makeSwapOnQuickSwap(); | |
updateUserBalanceRecord(_trader,_tokenTo, _amountTo); | |
} | |
/** | |
* @dev withdraw all of the ERC20 token from the contract address to the self-custodial owner | |
* NOTE: normally not to be used, and not made available in our UI, but available to maintain self-custody | |
*/ | |
function withdraw(address token) external | |
{ | |
uint amount = getBalance(token, msg.sender); | |
TransferHelper.safeTransfer(token, msg.sender, amount); | |
} | |
function isValidSignature( | |
bytes32 hash, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
public | |
constant | |
returns (bool) | |
{ | |
return isSigner[ecrecover( | |
keccak256("\x19Ethereum Signed Message:\n32", hash), | |
v, | |
r, | |
s | |
)]; | |
} | |
function keccak(address _trader, address _tokenFrom, uint _amountFrom, address _tokenTo, uint _amountTo, uint _validTill) public constant returns(bytes32) { | |
return keccak256(_trader, _tokenFrom, _tokenTo, _amountTo, _validTill); | |
} | |
/** | |
* @dev add or remove authorized users | |
* NOTE: only owner | |
*/ | |
function authorize(address user, bool value) external onlyOwner { | |
authorized[user] = value; | |
} | |
function transferOwner(address newOwner) external onlyOwner { | |
authorized[newOwner] = true; | |
authorized[owner()] = false; | |
transferOwnership(newOwner); | |
} | |
function renounceOwnership() public view override onlyOwner { | |
require(false, "Unable to renounce ownership"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment