Transaction Hash:
Block:
15311612 at Aug-10-2022 02:02:34 AM +UTC
Transaction Fee:
0.001618878415371318 ETH
$3.15
Gas Used:
151,642 Gas / 10.675659879 Gwei
Emitted Events:
| 99 |
RenERC20Proxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000032666b64e9fd0f44916e1378efb2cfa3b3b96e80, 00000000000000000000000000000000000000000000000006c1dc314fa70240 )
|
| 100 |
RenERC20Proxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e33417797d6b8aec9171d0d6516e88002fbe23e7, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 101 |
MintGatewayProxy.0xa58ba939eb08dab7eaf8ad09c16e7405ee88e5153e15da62d5481296a9f727fa( 0xa58ba939eb08dab7eaf8ad09c16e7405ee88e5153e15da62d5481296a9f727fa, 0x00000000000000000000000032666b64e9fd0f44916e1378efb2cfa3b3b96e80, 0x0000000000000000000000000000000000000000000000000000000000000241, 0x953e4c3221c00167127069e895223d9bbb3a16cd5b2b483ab1e89c6db6de1dff, 00000000000000000000000000000000000000000000000006c1dc314fa70240 )
|
| 102 |
RenERC20Proxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000032666b64e9fd0f44916e1378efb2cfa3b3b96e80, 0x0000000000000000000000007e68ba9764dbe23aaa685c71e02d2336cf447e5f, 00000000000000000000000000000000000000000000000006c1dc314fa70240 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x7E68Ba97...6cF447e5f |
0.01785183 Eth
Nonce: 0
|
0.016232951584628682 Eth
Nonce: 1
| 0.001618878415371318 | ||
| 0xD5147bc8...9b99276F5 | |||||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 1,177.04665935329525298 Eth | 1,177.047027695516282698 Eth | 0.000368342221029718 | |
| 0xED7D080A...Bb56BF1bf | (Ren: renFIL Gateway) |
Execution Trace
BasicAdapter.mint( _symbol=FIL, _recipient=0x7E68Ba9764DbE23aaa685C71E02D2336cF447e5f, _amount=486912339080577600, _nHash=953E4C3221C00167127069E895223D9BBB3A16CD5B2B483AB1E89C6DB6DE1DFF, _sig=0xC147BFC69B0B1556D53BCEF792F16D57970BEE16F34953D2A2F5402BBB5156083B8A0821163B5981EB080711B602686281EF769D0048C87BD1B8937796DCAFE81C )
-
GatewayRegistry.getGatewayBySymbol( _tokenSymbol=FIL ) => ( 0xED7D080AA1d2A4D468C615a5d481125Bb56BF1bf ) MintGatewayProxy.159ab14d( )MintGatewayLogicV1.mint( _pHash=231F192B69E51524D17DFD3617489A968DF59E7DACDD2A83E16B8820CA4ADEAB, _amountUnderlying=486912339080577600, _nHash=953E4C3221C00167127069E895223D9BBB3A16CD5B2B483AB1E89C6DB6DE1DFF, _sig=0xC147BFC69B0B1556D53BCEF792F16D57970BEE16F34953D2A2F5402BBB5156083B8A0821163B5981EB080711B602686281EF769D0048C87BD1B8937796DCAFE81C ) => ( 486912339080577600 )-
Null: 0x000...001.fffa3e94( )
RenERC20Proxy.a173b2f6( )
-
RenERC20LogicV1.fromUnderlying( _amountUnderlying=486912339080577600 ) => ( 486912339080577600 )
-
RenERC20Proxy.40c10f19( )
-
RenERC20LogicV1.mint( _to=0x32666B64e9fD0F44916E1378Efb2CFa3B3B96e80, _amount=486912339080577600 )
-
RenERC20Proxy.40c10f19( )
-
RenERC20LogicV1.mint( _to=0xE33417797d6b8Aec9171d0d6516E88002fbe23E7, _amount=0 )
-
RenERC20Proxy.eb438fc2( )
-
RenERC20LogicV1.toUnderlying( _amount=486912339080577600 ) => ( 486912339080577600 )
-
-
-
GatewayRegistry.getTokenBySymbol( _tokenSymbol=FIL ) => ( 0xD5147bc8e386d91Cc5DBE72099DAC6C9b99276F5 )
RenERC20Proxy.a9059cbb( )
-
RenERC20LogicV1.transfer( recipient=0x7E68Ba9764DbE23aaa685C71E02D2336cF447e5f, amount=486912339080577600 ) => ( True )
-
mint[BasicAdapter (ln:518)]
encode[BasicAdapter (ln:527)]mint[BasicAdapter (ln:528)]getGatewayBySymbol[BasicAdapter (ln:528)]transfer[BasicAdapter (ln:534)]getTokenBySymbol[BasicAdapter (ln:534)]
File 1 of 6: BasicAdapter
File 2 of 6: RenERC20Proxy
File 3 of 6: MintGatewayProxy
File 4 of 6: GatewayRegistry
File 5 of 6: MintGatewayLogicV1
File 6 of 6: RenERC20LogicV1
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 9068f80
Repository: https://github.com/renproject/darknode-sol
Issues: https://github.com/renproject/darknode-sol/issues
Licenses
@openzeppelin/contracts: (MIT) https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
darknode-sol: (GNU GPL V3) https://github.com/renproject/darknode-sol/blob/master/LICENSE
*/
pragma solidity 0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
contract IRelayRecipient {
function getHubAddr() public view returns (address);
function acceptRelayedCall(
address relay,
address from,
bytes calldata encodedFunction,
uint256 transactionFee,
uint256 gasPrice,
uint256 gasLimit,
uint256 nonce,
bytes calldata approvalData,
uint256 maxPossibleCharge
)
external
view
returns (uint256, bytes memory);
function preRelayedCall(bytes calldata context) external returns (bytes32);
function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external;
}
contract IRelayHub {
function stake(address relayaddr, uint256 unstakeDelay) external payable;
event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
function registerRelay(uint256 transactionFee, string memory url) public;
event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
function removeRelayByOwner(address relay) public;
event RelayRemoved(address indexed relay, uint256 unstakeTime);
function unstake(address relay) public;
event Unstaked(address indexed relay, uint256 stake);
enum RelayState {
Unknown,
Staked,
Registered,
Removed
}
function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
function depositFor(address target) public payable;
event Deposited(address indexed recipient, address indexed from, uint256 amount);
function balanceOf(address target) external view returns (uint256);
function withdraw(uint256 amount, address payable dest) public;
event Withdrawn(address indexed account, address indexed dest, uint256 amount);
function canRelay(
address relay,
address from,
address to,
bytes memory encodedFunction,
uint256 transactionFee,
uint256 gasPrice,
uint256 gasLimit,
uint256 nonce,
bytes memory signature,
bytes memory approvalData
) public view returns (uint256 status, bytes memory recipientContext);
enum PreconditionCheck {
OK,
WrongSignature,
WrongNonce,
AcceptRelayedCallReverted,
InvalidRecipientStatusCode
}
function relayCall(
address from,
address to,
bytes memory encodedFunction,
uint256 transactionFee,
uint256 gasPrice,
uint256 gasLimit,
uint256 nonce,
bytes memory signature,
bytes memory approvalData
) public;
event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
enum RelayCallStatus {
OK,
RelayedCallFailed,
PreRelayedFailed,
PostRelayedFailed,
RecipientBalanceChanged
}
function requiredGas(uint256 relayedCallStipend) public view returns (uint256);
function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) public view returns (uint256);
function penalizeRepeatedNonce(bytes memory unsignedTx1, bytes memory signature1, bytes memory unsignedTx2, bytes memory signature2) public;
function penalizeIllegalTransaction(bytes memory unsignedTx, bytes memory signature) public;
event Penalized(address indexed relay, address sender, uint256 amount);
function getNonce(address from) external view returns (uint256);
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract GSNRecipient is Initializable, IRelayRecipient, Context {
function initialize() public initializer {
if (_relayHub == address(0)) {
setDefaultRelayHub();
}
}
function setDefaultRelayHub() public {
_upgradeRelayHub(0xD216153c06E857cD7f72665E0aF1d7D82172F494);
}
address private _relayHub;
uint256 constant private RELAYED_CALL_ACCEPTED = 0;
uint256 constant private RELAYED_CALL_REJECTED = 11;
uint256 constant internal POST_RELAYED_CALL_MAX_GAS = 100000;
event RelayHubChanged(address indexed oldRelayHub, address indexed newRelayHub);
function getHubAddr() public view returns (address) {
return _relayHub;
}
function _upgradeRelayHub(address newRelayHub) internal {
address currentRelayHub = _relayHub;
require(newRelayHub != address(0), "GSNRecipient: new RelayHub is the zero address");
require(newRelayHub != currentRelayHub, "GSNRecipient: new RelayHub is the current one");
emit RelayHubChanged(currentRelayHub, newRelayHub);
_relayHub = newRelayHub;
}
function relayHubVersion() public view returns (string memory) {
this;
return "1.0.0";
}
function _withdrawDeposits(uint256 amount, address payable payee) internal {
IRelayHub(_relayHub).withdraw(amount, payee);
}
function _msgSender() internal view returns (address payable) {
if (msg.sender != _relayHub) {
return msg.sender;
} else {
return _getRelayedCallSender();
}
}
function _msgData() internal view returns (bytes memory) {
if (msg.sender != _relayHub) {
return msg.data;
} else {
return _getRelayedCallData();
}
}
function preRelayedCall(bytes calldata context) external returns (bytes32) {
require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
return _preRelayedCall(context);
}
function _preRelayedCall(bytes memory context) internal returns (bytes32);
function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external {
require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
_postRelayedCall(context, success, actualCharge, preRetVal);
}
function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal;
function _approveRelayedCall() internal pure returns (uint256, bytes memory) {
return _approveRelayedCall("");
}
function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
return (RELAYED_CALL_ACCEPTED, context);
}
function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
return (RELAYED_CALL_REJECTED + errorCode, "");
}
function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) {
return (gas * gasPrice * (100 + serviceFee)) / 100;
}
function _getRelayedCallSender() private pure returns (address payable result) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
}
return result;
}
function _getRelayedCallData() private pure returns (bytes memory) {
uint256 actualDataLength = msg.data.length - 20;
bytes memory actualData = new bytes(actualDataLength);
for (uint256 i = 0; i < actualDataLength; ++i) {
actualData[i] = msg.data[i];
}
return actualData;
}
}
interface IMintGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
}
interface IBurnGateway {
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
interface IGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IGatewayRegistry {
event LogGatewayRegistered(
string _symbol,
string indexed _indexedSymbol,
address indexed _tokenAddress,
address indexed _gatewayAddress
);
event LogGatewayDeregistered(
string _symbol,
string indexed _indexedSymbol,
address indexed _tokenAddress,
address indexed _gatewayAddress
);
event LogGatewayUpdated(
address indexed _tokenAddress,
address indexed _currentGatewayAddress,
address indexed _newGatewayAddress
);
function getGateways(address _start, uint256 _count)
external
view
returns (address[] memory);
function getRenTokens(address _start, uint256 _count)
external
view
returns (address[] memory);
function getGatewayByToken(address _tokenAddress)
external
view
returns (IGateway);
function getGatewayBySymbol(string calldata _tokenSymbol)
external
view
returns (IGateway);
function getTokenBySymbol(string calldata _tokenSymbol)
external
view
returns (IERC20);
}
contract BasicAdapter is GSNRecipient {
IGatewayRegistry registry;
constructor(IGatewayRegistry _registry) public {
GSNRecipient.initialize();
registry = _registry;
}
function mint(
string calldata _symbol,
address _recipient,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external {
bytes32 payloadHash = keccak256(abi.encode(_symbol, _recipient));
uint256 amount = registry.getGatewayBySymbol(_symbol).mint(
payloadHash,
_amount,
_nHash,
_sig
);
registry.getTokenBySymbol(_symbol).transfer(_recipient, amount);
}
function burn(string calldata _symbol, bytes calldata _to, uint256 _amount)
external
{
require(
registry.getTokenBySymbol(_symbol).transferFrom(
_msgSender(),
address(this),
_amount
),
"token transfer failed"
);
registry.getGatewayBySymbol(_symbol).burn(_to, _amount);
}
function acceptRelayedCall(
address relay,
address from,
bytes calldata encodedFunction,
uint256 transactionFee,
uint256 gasPrice,
uint256 gasLimit,
uint256 nonce,
bytes calldata approvalData,
uint256 maxPossibleCharge
) external view returns (uint256, bytes memory) {
return _approveRelayedCall();
}
function _preRelayedCall(bytes memory context) internal returns (bytes32) {}
function _postRelayedCall(
bytes memory context,
bool,
uint256 actualCharge,
bytes32
) internal {}
}File 2 of 6: RenERC20Proxy
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 1e106b3
Repository: https://github.com/renproject/gateway-sol
Issues: https://github.com/renproject/gateway-sol/issues
Licenses
@openzeppelin/contracts: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
gateway-sol: https://github.com/renproject/gateway-sol/blob/master/LICENSE
*/
pragma solidity ^0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract Proxy {
function () payable external {
_fallback();
}
function _implementation() internal view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize)
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch result
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
function _willFallback() internal {
}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
library OpenZeppelinUpgradesAddress {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
contract BaseUpgradeabilityProxy is Proxy {
event Upgraded(address indexed implementation);
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
constructor(address _logic, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
function initialize(address _logic, bytes memory _data) public payable {
require(_implementation() == address(0));
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy {
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
InitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
_setAdmin(_admin);
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contract ERC20 is Initializable, Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
uint256[50] private ______gap;
}
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
contract Claimable is Initializable, Ownable {
address public pendingOwner;
function initialize(address _nextOwner) public initializer {
Ownable.initialize(_nextOwner);
}
modifier onlyPendingOwner() {
require(
_msgSender() == pendingOwner,
"Claimable: caller is not the pending owner"
);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != owner() && newOwner != pendingOwner,
"Claimable: invalid new owner"
);
pendingOwner = newOwner;
}
function claimOwnership() public onlyPendingOwner {
_transferOwnership(pendingOwner);
delete pendingOwner;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract CanReclaimTokens is Claimable {
using SafeERC20 for ERC20;
mapping(address => bool) private recoverableTokensBlacklist;
function initialize(address _nextOwner) public initializer {
Claimable.initialize(_nextOwner);
}
function blacklistRecoverableToken(address _token) public onlyOwner {
recoverableTokensBlacklist[_token] = true;
}
function recoverTokens(address _token) external onlyOwner {
require(
!recoverableTokensBlacklist[_token],
"CanReclaimTokens: token is not recoverable"
);
if (_token == address(0x0)) {
msg.sender.transfer(address(this).balance);
} else {
ERC20(_token).safeTransfer(
msg.sender,
ERC20(_token).balanceOf(address(this))
);
}
}
}
contract ERC20WithRate is Initializable, Ownable, ERC20 {
using SafeMath for uint256;
uint256 public constant _rateScale = 1e18;
uint256 internal _rate;
event LogRateChanged(uint256 indexed _rate);
function initialize(address _nextOwner, uint256 _initialRate)
public
initializer
{
Ownable.initialize(_nextOwner);
_setRate(_initialRate);
}
function setExchangeRate(uint256 _nextRate) public onlyOwner {
_setRate(_nextRate);
}
function exchangeRateCurrent() public view returns (uint256) {
require(_rate != 0, "ERC20WithRate: rate has not been initialized");
return _rate;
}
function _setRate(uint256 _nextRate) internal {
require(_nextRate > 0, "ERC20WithRate: rate must be greater than zero");
_rate = _nextRate;
}
function balanceOfUnderlying(address _account)
public
view
returns (uint256)
{
return toUnderlying(balanceOf(_account));
}
function toUnderlying(uint256 _amount) public view returns (uint256) {
return _amount.mul(_rate).div(_rateScale);
}
function fromUnderlying(uint256 _amountUnderlying)
public
view
returns (uint256)
{
return _amountUnderlying.mul(_rateScale).div(_rate);
}
}
contract ERC20WithPermit is Initializable, ERC20, ERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) public nonces;
string public version;
bytes32 public DOMAIN_SEPARATOR;
bytes32
public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
function initialize(
uint256 _chainId,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
version = _version;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes(version)),
_chainId,
address(this)
)
);
}
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed
)
)
)
);
require(holder != address(0), "ERC20WithRate: address must not be 0x0");
require(
holder == ecrecover(digest, v, r, s),
"ERC20WithRate: invalid signature"
);
require(
expiry == 0 || now <= expiry,
"ERC20WithRate: permit has expired"
);
require(nonce == nonces[holder]++, "ERC20WithRate: invalid nonce");
uint256 amount = allowed ? uint256(-1) : 0;
_approve(holder, spender, amount);
}
}
contract RenERC20LogicV1 is
Initializable,
ERC20,
ERC20Detailed,
ERC20WithRate,
ERC20WithPermit,
Claimable,
CanReclaimTokens
{
function initialize(
uint256 _chainId,
address _nextOwner,
uint256 _initialRate,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
ERC20WithRate.initialize(_nextOwner, _initialRate);
ERC20WithPermit.initialize(
_chainId,
_version,
_name,
_symbol,
_decimals
);
Claimable.initialize(_nextOwner);
CanReclaimTokens.initialize(_nextOwner);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transferFrom(sender, recipient, amount);
}
}
contract RenERC20Proxy is InitializableAdminUpgradeabilityProxy {
}File 3 of 6: MintGatewayProxy
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 1e106b3
Repository: https://github.com/renproject/gateway-sol
Issues: https://github.com/renproject/gateway-sol/issues
Licenses
@openzeppelin/contracts: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
gateway-sol: https://github.com/renproject/gateway-sol/blob/master/LICENSE
*/
pragma solidity ^0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library ECDSA {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
if (signature.length != 65) {
revert("ECDSA: signature length is invalid");
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert("ECDSA: signature.s is in the wrong range");
}
if (v != 27 && v != 28) {
revert("ECDSA: signature.v is in the wrong range");
}
return ecrecover(hash, v, r, s);
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
contract Proxy {
function () payable external {
_fallback();
}
function _implementation() internal view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize)
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch result
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
function _willFallback() internal {
}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
library OpenZeppelinUpgradesAddress {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
contract BaseUpgradeabilityProxy is Proxy {
event Upgraded(address indexed implementation);
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
constructor(address _logic, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
function initialize(address _logic, bytes memory _data) public payable {
require(_implementation() == address(0));
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy {
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
InitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
_setAdmin(_admin);
}
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract Claimable is Initializable, Ownable {
address public pendingOwner;
function initialize(address _nextOwner) public initializer {
Ownable.initialize(_nextOwner);
}
modifier onlyPendingOwner() {
require(
_msgSender() == pendingOwner,
"Claimable: caller is not the pending owner"
);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != owner() && newOwner != pendingOwner,
"Claimable: invalid new owner"
);
pendingOwner = newOwner;
}
function claimOwnership() public onlyPendingOwner {
_transferOwnership(pendingOwner);
delete pendingOwner;
}
}
library String {
function fromUint(uint256 _i) internal pure returns (string memory) {
if (_i == 0) {
return "0";
}
uint256 j = _i;
uint256 len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint256 k = len - 1;
while (_i != 0) {
bstr[k--] = bytes1(uint8(48 + (_i % 10)));
_i /= 10;
}
return string(bstr);
}
function fromBytes32(bytes32 _value) internal pure returns (string memory) {
bytes memory alphabet = "0123456789abcdef";
bytes memory str = new bytes(32 * 2 + 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < 32; i++) {
str[2 + i * 2] = alphabet[uint256(uint8(_value[i] >> 4))];
str[3 + i * 2] = alphabet[uint256(uint8(_value[i] & 0x0f))];
}
return string(str);
}
function fromAddress(address _addr) internal pure returns (string memory) {
bytes32 value = bytes32(uint256(_addr));
bytes memory alphabet = "0123456789abcdef";
bytes memory str = new bytes(20 * 2 + 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < 20; i++) {
str[2 + i * 2] = alphabet[uint256(uint8(value[i + 12] >> 4))];
str[3 + i * 2] = alphabet[uint256(uint8(value[i + 12] & 0x0f))];
}
return string(str);
}
function add8(
string memory a,
string memory b,
string memory c,
string memory d,
string memory e,
string memory f,
string memory g,
string memory h
) internal pure returns (string memory) {
return string(abi.encodePacked(a, b, c, d, e, f, g, h));
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract ERC20 is Initializable, Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
uint256[50] private ______gap;
}
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract CanReclaimTokens is Claimable {
using SafeERC20 for ERC20;
mapping(address => bool) private recoverableTokensBlacklist;
function initialize(address _nextOwner) public initializer {
Claimable.initialize(_nextOwner);
}
function blacklistRecoverableToken(address _token) public onlyOwner {
recoverableTokensBlacklist[_token] = true;
}
function recoverTokens(address _token) external onlyOwner {
require(
!recoverableTokensBlacklist[_token],
"CanReclaimTokens: token is not recoverable"
);
if (_token == address(0x0)) {
msg.sender.transfer(address(this).balance);
} else {
ERC20(_token).safeTransfer(
msg.sender,
ERC20(_token).balanceOf(address(this))
);
}
}
}
contract ERC20WithRate is Initializable, Ownable, ERC20 {
using SafeMath for uint256;
uint256 public constant _rateScale = 1e18;
uint256 internal _rate;
event LogRateChanged(uint256 indexed _rate);
function initialize(address _nextOwner, uint256 _initialRate)
public
initializer
{
Ownable.initialize(_nextOwner);
_setRate(_initialRate);
}
function setExchangeRate(uint256 _nextRate) public onlyOwner {
_setRate(_nextRate);
}
function exchangeRateCurrent() public view returns (uint256) {
require(_rate != 0, "ERC20WithRate: rate has not been initialized");
return _rate;
}
function _setRate(uint256 _nextRate) internal {
require(_nextRate > 0, "ERC20WithRate: rate must be greater than zero");
_rate = _nextRate;
}
function balanceOfUnderlying(address _account)
public
view
returns (uint256)
{
return toUnderlying(balanceOf(_account));
}
function toUnderlying(uint256 _amount) public view returns (uint256) {
return _amount.mul(_rate).div(_rateScale);
}
function fromUnderlying(uint256 _amountUnderlying)
public
view
returns (uint256)
{
return _amountUnderlying.mul(_rateScale).div(_rate);
}
}
contract ERC20WithPermit is Initializable, ERC20, ERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) public nonces;
string public version;
bytes32 public DOMAIN_SEPARATOR;
bytes32
public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
function initialize(
uint256 _chainId,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
version = _version;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes(version)),
_chainId,
address(this)
)
);
}
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed
)
)
)
);
require(holder != address(0), "ERC20WithRate: address must not be 0x0");
require(
holder == ecrecover(digest, v, r, s),
"ERC20WithRate: invalid signature"
);
require(
expiry == 0 || now <= expiry,
"ERC20WithRate: permit has expired"
);
require(nonce == nonces[holder]++, "ERC20WithRate: invalid nonce");
uint256 amount = allowed ? uint256(-1) : 0;
_approve(holder, spender, amount);
}
}
contract RenERC20LogicV1 is
Initializable,
ERC20,
ERC20Detailed,
ERC20WithRate,
ERC20WithPermit,
Claimable,
CanReclaimTokens
{
function initialize(
uint256 _chainId,
address _nextOwner,
uint256 _initialRate,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
ERC20WithRate.initialize(_nextOwner, _initialRate);
ERC20WithPermit.initialize(
_chainId,
_version,
_name,
_symbol,
_decimals
);
Claimable.initialize(_nextOwner);
CanReclaimTokens.initialize(_nextOwner);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transferFrom(sender, recipient, amount);
}
}
contract RenERC20Proxy is InitializableAdminUpgradeabilityProxy {
}
interface IMintGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
}
interface IBurnGateway {
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
interface IGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
contract GatewayStateV1 {
uint256 constant BIPS_DENOMINATOR = 10000;
uint256 public minimumBurnAmount;
RenERC20LogicV1 public token;
address public mintAuthority;
address public feeRecipient;
uint16 public mintFee;
uint16 public burnFee;
mapping(bytes32 => bool) public status;
uint256 public nextN = 0;
}
contract GatewayStateV2 {
struct Burn {
uint256 _blocknumber;
bytes _to;
uint256 _amount;
string _chain;
bytes _payload;
}
mapping(uint256 => Burn) internal burns;
bytes32 public selectorHash;
}
contract MintGatewayLogicV1 is
Initializable,
Claimable,
CanReclaimTokens,
IGateway,
GatewayStateV1,
GatewayStateV2
{
using SafeMath for uint256;
event LogMintAuthorityUpdated(address indexed _newMintAuthority);
event LogMint(
address indexed _to,
uint256 _amount,
uint256 indexed _n,
bytes32 indexed _nHash
);
event LogBurn(
bytes _to,
uint256 _amount,
uint256 indexed _n,
bytes indexed _indexedTo
);
modifier onlyOwnerOrMintAuthority() {
require(
msg.sender == mintAuthority || msg.sender == owner(),
"MintGateway: caller is not the owner or mint authority"
);
_;
}
function initialize(
RenERC20LogicV1 _token,
address _feeRecipient,
address _mintAuthority,
uint16 _mintFee,
uint16 _burnFee,
uint256 _minimumBurnAmount
) public initializer {
Claimable.initialize(msg.sender);
CanReclaimTokens.initialize(msg.sender);
minimumBurnAmount = _minimumBurnAmount;
token = _token;
mintFee = _mintFee;
burnFee = _burnFee;
updateMintAuthority(_mintAuthority);
updateFeeRecipient(_feeRecipient);
}
function updateSelectorHash(bytes32 _selectorHash) public onlyOwner {
selectorHash = _selectorHash;
}
function claimTokenOwnership() public {
token.claimOwnership();
}
function transferTokenOwnership(MintGatewayLogicV1 _nextTokenOwner)
public
onlyOwner
{
token.transferOwnership(address(_nextTokenOwner));
_nextTokenOwner.claimTokenOwnership();
}
function updateMintAuthority(address _nextMintAuthority)
public
onlyOwnerOrMintAuthority
{
require(
_nextMintAuthority != address(0),
"MintGateway: mintAuthority cannot be set to address zero"
);
mintAuthority = _nextMintAuthority;
emit LogMintAuthorityUpdated(mintAuthority);
}
function updateMinimumBurnAmount(uint256 _minimumBurnAmount)
public
onlyOwner
{
minimumBurnAmount = _minimumBurnAmount;
}
function updateFeeRecipient(address _nextFeeRecipient) public onlyOwner {
require(
_nextFeeRecipient != address(0x0),
"MintGateway: fee recipient cannot be 0x0"
);
feeRecipient = _nextFeeRecipient;
}
function updateMintFee(uint16 _nextMintFee) public onlyOwner {
mintFee = _nextMintFee;
}
function updateBurnFee(uint16 _nextBurnFee) public onlyOwner {
burnFee = _nextBurnFee;
}
function mint(
bytes32 _pHash,
uint256 _amountUnderlying,
bytes32 _nHash,
bytes memory _sig
) public returns (uint256) {
bytes32 sigHash = hashForSignature(
_pHash,
_amountUnderlying,
msg.sender,
_nHash
);
require(
status[sigHash] == false,
"MintGateway: nonce hash already spent"
);
if (!verifySignature(sigHash, _sig)) {
revert(
String.add8(
"MintGateway: invalid signature. pHash: ",
String.fromBytes32(_pHash),
", amount: ",
String.fromUint(_amountUnderlying),
", msg.sender: ",
String.fromAddress(msg.sender),
", _nHash: ",
String.fromBytes32(_nHash)
)
);
}
status[sigHash] = true;
uint256 amountScaled = token.fromUnderlying(_amountUnderlying);
uint256 absoluteFeeScaled = amountScaled.mul(mintFee).div(
BIPS_DENOMINATOR
);
uint256 receivedAmountScaled = amountScaled.sub(
absoluteFeeScaled,
"MintGateway: fee exceeds amount"
);
token.mint(msg.sender, receivedAmountScaled);
token.mint(feeRecipient, absoluteFeeScaled);
uint256 receivedAmountUnderlying = token.toUnderlying(
receivedAmountScaled
);
emit LogMint(msg.sender, receivedAmountUnderlying, nextN, _nHash);
nextN += 1;
return receivedAmountScaled;
}
function burn(bytes memory _to, uint256 _amount) public returns (uint256) {
require(_to.length != 0, "MintGateway: to address is empty");
uint256 fee = _amount.mul(burnFee).div(BIPS_DENOMINATOR);
uint256 amountAfterFee = _amount.sub(
fee,
"MintGateway: fee exceeds amount"
);
uint256 amountAfterFeeUnderlying = token.toUnderlying(amountAfterFee);
token.burn(msg.sender, _amount);
token.mint(feeRecipient, fee);
require(
amountAfterFeeUnderlying > minimumBurnAmount,
"MintGateway: amount is less than the minimum burn amount"
);
emit LogBurn(_to, amountAfterFeeUnderlying, nextN, _to);
bytes memory payload;
GatewayStateV2.burns[nextN] = Burn({
_blocknumber: block.number,
_to: _to,
_amount: amountAfterFeeUnderlying,
_chain: "",
_payload: payload
});
nextN += 1;
return amountAfterFeeUnderlying;
}
function getBurn(uint256 _n)
public
view
returns (
uint256 _blocknumber,
bytes memory _to,
uint256 _amount,
string memory _chain,
bytes memory _payload
)
{
Burn memory burnStruct = GatewayStateV2.burns[_n];
require(burnStruct._to.length > 0, "MintGateway: burn not found");
return (
burnStruct._blocknumber,
burnStruct._to,
burnStruct._amount,
burnStruct._chain,
burnStruct._payload
);
}
function verifySignature(bytes32 _sigHash, bytes memory _sig)
public
view
returns (bool)
{
return mintAuthority == ECDSA.recover(_sigHash, _sig);
}
function hashForSignature(
bytes32 _pHash,
uint256 _amount,
address _to,
bytes32 _nHash
) public view returns (bytes32) {
return
keccak256(abi.encode(_pHash, _amount, selectorHash, _to, _nHash));
}
}
contract MintGatewayProxy is InitializableAdminUpgradeabilityProxy {
}File 4 of 6: GatewayRegistry
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 9068f80
Repository: https://github.com/renproject/darknode-sol
Issues: https://github.com/renproject/darknode-sol/issues
Licenses
@openzeppelin/contracts: (MIT) https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
darknode-sol: (GNU GPL V3) https://github.com/renproject/darknode-sol/blob/master/LICENSE
*/
pragma solidity 0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract Claimable is Initializable, Ownable {
address public pendingOwner;
function initialize(address _nextOwner) public initializer {
Ownable.initialize(_nextOwner);
}
modifier onlyPendingOwner() {
require(
_msgSender() == pendingOwner,
"Claimable: caller is not the pending owner"
);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != owner() && newOwner != pendingOwner,
"Claimable: invalid new owner"
);
pendingOwner = newOwner;
}
function claimOwnership() public onlyPendingOwner {
_transferOwnership(pendingOwner);
delete pendingOwner;
}
}
contract Proxy {
function () payable external {
_fallback();
}
function _implementation() internal view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize)
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch result
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
function _willFallback() internal {
}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
library OpenZeppelinUpgradesAddress {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
contract BaseUpgradeabilityProxy is Proxy {
event Upgraded(address indexed implementation);
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
constructor(address _logic, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
function initialize(address _logic, bytes memory _data) public payable {
require(_implementation() == address(0));
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy {
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
InitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
_setAdmin(_admin);
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contract ERC20 is Initializable, Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
uint256[50] private ______gap;
}
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != 0x0 && codehash != accountHash);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract CanReclaimTokens is Claimable {
using SafeERC20 for ERC20;
mapping(address => bool) private recoverableTokensBlacklist;
function initialize(address _nextOwner) public initializer {
Claimable.initialize(_nextOwner);
}
function blacklistRecoverableToken(address _token) public onlyOwner {
recoverableTokensBlacklist[_token] = true;
}
function recoverTokens(address _token) external onlyOwner {
require(
!recoverableTokensBlacklist[_token],
"CanReclaimTokens: token is not recoverable"
);
if (_token == address(0x0)) {
msg.sender.transfer(address(this).balance);
} else {
ERC20(_token).safeTransfer(
msg.sender,
ERC20(_token).balanceOf(address(this))
);
}
}
}
contract ERC20WithRate is Initializable, Ownable, ERC20 {
using SafeMath for uint256;
uint256 public constant _rateScale = 1e18;
uint256 internal _rate;
event LogRateChanged(uint256 indexed _rate);
function initialize(address _nextOwner, uint256 _initialRate)
public
initializer
{
Ownable.initialize(_nextOwner);
_setRate(_initialRate);
}
function setExchangeRate(uint256 _nextRate) public onlyOwner {
_setRate(_nextRate);
}
function exchangeRateCurrent() public view returns (uint256) {
require(_rate != 0, "ERC20WithRate: rate has not been initialized");
return _rate;
}
function _setRate(uint256 _nextRate) internal {
require(_nextRate > 0, "ERC20WithRate: rate must be greater than zero");
_rate = _nextRate;
}
function balanceOfUnderlying(address _account)
public
view
returns (uint256)
{
return toUnderlying(balanceOf(_account));
}
function toUnderlying(uint256 _amount) public view returns (uint256) {
return _amount.mul(_rate).div(_rateScale);
}
function fromUnderlying(uint256 _amountUnderlying)
public
view
returns (uint256)
{
return _amountUnderlying.mul(_rateScale).div(_rate);
}
}
contract ERC20WithPermit is Initializable, ERC20, ERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) public nonces;
string public version;
bytes32 public DOMAIN_SEPARATOR;
bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
function initialize(
uint256 _chainId,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
version = _version;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes(version)),
_chainId,
address(this)
)
);
}
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed
)
)
)
);
require(holder != address(0), "ERC20WithRate: address must not be 0x0");
require(
holder == ecrecover(digest, v, r, s),
"ERC20WithRate: invalid signature"
);
require(
expiry == 0 || now <= expiry,
"ERC20WithRate: permit has expired"
);
require(nonce == nonces[holder]++, "ERC20WithRate: invalid nonce");
uint256 amount = allowed ? uint256(-1) : 0;
_approve(holder, spender, amount);
}
}
contract RenERC20LogicV1 is
Initializable,
ERC20,
ERC20Detailed,
ERC20WithRate,
ERC20WithPermit,
Claimable,
CanReclaimTokens
{
function initialize(
uint256 _chainId,
address _nextOwner,
uint256 _initialRate,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
ERC20WithRate.initialize(_nextOwner, _initialRate);
ERC20WithPermit.initialize(
_chainId,
_version,
_name,
_symbol,
_decimals
);
Claimable.initialize(_nextOwner);
CanReclaimTokens.initialize(_nextOwner);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transfer(recipient, amount);
}
function transferFrom(address sender, address recipient, uint256 amount)
public
returns (bool)
{
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transferFrom(sender, recipient, amount);
}
}
contract RenBTC is InitializableAdminUpgradeabilityProxy {}
contract RenZEC is InitializableAdminUpgradeabilityProxy {}
contract RenBCH is InitializableAdminUpgradeabilityProxy {}
library LinkedList {
address public constant NULL = address(0);
struct Node {
bool inList;
address previous;
address next;
}
struct List {
mapping (address => Node) list;
}
function insertBefore(List storage self, address target, address newNode) internal {
require(newNode != address(0), "LinkedList: invalid address");
require(!isInList(self, newNode), "LinkedList: already in list");
require(isInList(self, target) || target == NULL, "LinkedList: not in list");
address prev = self.list[target].previous;
self.list[newNode].next = target;
self.list[newNode].previous = prev;
self.list[target].previous = newNode;
self.list[prev].next = newNode;
self.list[newNode].inList = true;
}
function insertAfter(List storage self, address target, address newNode) internal {
require(newNode != address(0), "LinkedList: invalid address");
require(!isInList(self, newNode), "LinkedList: already in list");
require(isInList(self, target) || target == NULL, "LinkedList: not in list");
address n = self.list[target].next;
self.list[newNode].previous = target;
self.list[newNode].next = n;
self.list[target].next = newNode;
self.list[n].previous = newNode;
self.list[newNode].inList = true;
}
function remove(List storage self, address node) internal {
require(isInList(self, node), "LinkedList: not in list");
address p = self.list[node].previous;
address n = self.list[node].next;
self.list[p].next = n;
self.list[n].previous = p;
self.list[node].inList = false;
delete self.list[node];
}
function prepend(List storage self, address node) internal {
insertBefore(self, begin(self), node);
}
function append(List storage self, address node) internal {
insertAfter(self, end(self), node);
}
function swap(List storage self, address left, address right) internal {
address previousRight = self.list[right].previous;
remove(self, right);
insertAfter(self, left, right);
remove(self, left);
insertAfter(self, previousRight, left);
}
function isInList(List storage self, address node) internal view returns (bool) {
return self.list[node].inList;
}
function begin(List storage self) internal view returns (address) {
return self.list[NULL].next;
}
function end(List storage self) internal view returns (address) {
return self.list[NULL].previous;
}
function next(List storage self, address node) internal view returns (address) {
require(isInList(self, node), "LinkedList: not in list");
return self.list[node].next;
}
function previous(List storage self, address node) internal view returns (address) {
require(isInList(self, node), "LinkedList: not in list");
return self.list[node].previous;
}
function elements(List storage self, address _start, uint256 _count) internal view returns (address[] memory) {
require(_count > 0, "LinkedList: invalid count");
require(isInList(self, _start) || _start == address(0), "LinkedList: not in list");
address[] memory elems = new address[](_count);
uint256 n = 0;
address nextItem = _start;
if (nextItem == address(0)) {
nextItem = begin(self);
}
while (n < _count) {
if (nextItem == address(0)) {
break;
}
elems[n] = nextItem;
nextItem = next(self, nextItem);
n += 1;
}
return elems;
}
}
interface IMintGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
}
interface IBurnGateway {
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
interface IGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
contract GatewayRegistry is Claimable, CanReclaimTokens {
constructor() public {
Claimable.initialize(msg.sender);
CanReclaimTokens.initialize(msg.sender);
}
event LogGatewayRegistered(
string _symbol,
string indexed _indexedSymbol,
address indexed _token,
address indexed _gatewayContract
);
event LogGatewayDeregistered(
string _symbol,
string indexed _indexedSymbol,
address indexed _token,
address indexed _gatewayContract
);
event LogGatewayUpdated(
address indexed _token,
address indexed _currentGatewayContract,
address indexed _newGatewayContract
);
uint256 numGatewayContracts = 0;
LinkedList.List private gatewayContractList;
LinkedList.List private renTokenList;
mapping(address => address) private gatewayByToken;
mapping(string => address) private tokenBySymbol;
function setGateway(string calldata _symbol, address _token, address _gatewayContract)
external
onlyOwner
{
require(symbolIsValid(_symbol), "GatewayRegistry: symbol must be alphanumeric");
require(
!LinkedList.isInList(gatewayContractList, _gatewayContract),
"GatewayRegistry: gateway already registered"
);
require(
gatewayByToken[_token] == address(0x0),
"GatewayRegistry: token already registered"
);
require(
tokenBySymbol[_symbol] == address(0x0),
"GatewayRegistry: symbol already registered"
);
LinkedList.append(gatewayContractList, _gatewayContract);
LinkedList.append(renTokenList, _token);
tokenBySymbol[_symbol] = _token;
gatewayByToken[_token] = _gatewayContract;
numGatewayContracts += 1;
emit LogGatewayRegistered(_symbol, _symbol, _token, _gatewayContract);
}
function updateGateway(address _token, address _newGatewayContract)
external
onlyOwner
{
address currentGateway = gatewayByToken[_token];
require(
currentGateway != address(0x0),
"GatewayRegistry: token not registered"
);
LinkedList.remove(gatewayContractList, currentGateway);
LinkedList.append(gatewayContractList, _newGatewayContract);
gatewayByToken[_token] = _newGatewayContract;
emit LogGatewayUpdated(_token, currentGateway, _newGatewayContract);
}
function removeGateway(string calldata _symbol) external onlyOwner {
address tokenAddress = tokenBySymbol[_symbol];
require(
tokenAddress != address(0x0),
"GatewayRegistry: symbol not registered"
);
address gatewayAddress = gatewayByToken[tokenAddress];
delete gatewayByToken[tokenAddress];
delete tokenBySymbol[_symbol];
LinkedList.remove(gatewayContractList, gatewayAddress);
LinkedList.remove(renTokenList, tokenAddress);
numGatewayContracts -= 1;
emit LogGatewayDeregistered(
_symbol,
_symbol,
tokenAddress,
gatewayAddress
);
}
function getGateways(address _start, uint256 _count)
external
view
returns (address[] memory)
{
return
LinkedList.elements(
gatewayContractList,
_start,
_count == 0 ? numGatewayContracts : _count
);
}
function getRenTokens(address _start, uint256 _count)
external
view
returns (address[] memory)
{
return
LinkedList.elements(
renTokenList,
_start,
_count == 0 ? numGatewayContracts : _count
);
}
function getGatewayByToken(address _token)
external
view
returns (IGateway)
{
return IGateway(gatewayByToken[_token]);
}
function getGatewayBySymbol(string calldata _tokenSymbol)
external
view
returns (IGateway)
{
return IGateway(gatewayByToken[tokenBySymbol[_tokenSymbol]]);
}
function getTokenBySymbol(string calldata _tokenSymbol)
external
view
returns (IERC20)
{
return IERC20(tokenBySymbol[_tokenSymbol]);
}
function symbolIsValid(string memory _tokenSymbol) public pure returns (bool) {
for (uint i = 0; i < bytes(_tokenSymbol).length; i++) {
uint8 char = uint8(bytes(_tokenSymbol)[i]);
if (!(
(char >= 65 && char <= 90) ||
(char >= 97 && char <= 122) ||
(char >= 48 && char <= 57)
)) {
return false;
}
}
return true;
}
}File 5 of 6: MintGatewayLogicV1
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 1e106b3
Repository: https://github.com/renproject/gateway-sol
Issues: https://github.com/renproject/gateway-sol/issues
Licenses
@openzeppelin/contracts: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
gateway-sol: https://github.com/renproject/gateway-sol/blob/master/LICENSE
*/
pragma solidity ^0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library ECDSA {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
if (signature.length != 65) {
revert("ECDSA: signature length is invalid");
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert("ECDSA: signature.s is in the wrong range");
}
if (v != 27 && v != 28) {
revert("ECDSA: signature.v is in the wrong range");
}
return ecrecover(hash, v, r, s);
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
contract Proxy {
function () payable external {
_fallback();
}
function _implementation() internal view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize)
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch result
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
function _willFallback() internal {
}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
library OpenZeppelinUpgradesAddress {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
contract BaseUpgradeabilityProxy is Proxy {
event Upgraded(address indexed implementation);
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
constructor(address _logic, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
function initialize(address _logic, bytes memory _data) public payable {
require(_implementation() == address(0));
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy {
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
InitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
_setAdmin(_admin);
}
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract Claimable is Initializable, Ownable {
address public pendingOwner;
function initialize(address _nextOwner) public initializer {
Ownable.initialize(_nextOwner);
}
modifier onlyPendingOwner() {
require(
_msgSender() == pendingOwner,
"Claimable: caller is not the pending owner"
);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != owner() && newOwner != pendingOwner,
"Claimable: invalid new owner"
);
pendingOwner = newOwner;
}
function claimOwnership() public onlyPendingOwner {
_transferOwnership(pendingOwner);
delete pendingOwner;
}
}
library String {
function fromUint(uint256 _i) internal pure returns (string memory) {
if (_i == 0) {
return "0";
}
uint256 j = _i;
uint256 len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint256 k = len - 1;
while (_i != 0) {
bstr[k--] = bytes1(uint8(48 + (_i % 10)));
_i /= 10;
}
return string(bstr);
}
function fromBytes32(bytes32 _value) internal pure returns (string memory) {
bytes memory alphabet = "0123456789abcdef";
bytes memory str = new bytes(32 * 2 + 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < 32; i++) {
str[2 + i * 2] = alphabet[uint256(uint8(_value[i] >> 4))];
str[3 + i * 2] = alphabet[uint256(uint8(_value[i] & 0x0f))];
}
return string(str);
}
function fromAddress(address _addr) internal pure returns (string memory) {
bytes32 value = bytes32(uint256(_addr));
bytes memory alphabet = "0123456789abcdef";
bytes memory str = new bytes(20 * 2 + 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < 20; i++) {
str[2 + i * 2] = alphabet[uint256(uint8(value[i + 12] >> 4))];
str[3 + i * 2] = alphabet[uint256(uint8(value[i + 12] & 0x0f))];
}
return string(str);
}
function add8(
string memory a,
string memory b,
string memory c,
string memory d,
string memory e,
string memory f,
string memory g,
string memory h
) internal pure returns (string memory) {
return string(abi.encodePacked(a, b, c, d, e, f, g, h));
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract ERC20 is Initializable, Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
uint256[50] private ______gap;
}
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract CanReclaimTokens is Claimable {
using SafeERC20 for ERC20;
mapping(address => bool) private recoverableTokensBlacklist;
function initialize(address _nextOwner) public initializer {
Claimable.initialize(_nextOwner);
}
function blacklistRecoverableToken(address _token) public onlyOwner {
recoverableTokensBlacklist[_token] = true;
}
function recoverTokens(address _token) external onlyOwner {
require(
!recoverableTokensBlacklist[_token],
"CanReclaimTokens: token is not recoverable"
);
if (_token == address(0x0)) {
msg.sender.transfer(address(this).balance);
} else {
ERC20(_token).safeTransfer(
msg.sender,
ERC20(_token).balanceOf(address(this))
);
}
}
}
contract ERC20WithRate is Initializable, Ownable, ERC20 {
using SafeMath for uint256;
uint256 public constant _rateScale = 1e18;
uint256 internal _rate;
event LogRateChanged(uint256 indexed _rate);
function initialize(address _nextOwner, uint256 _initialRate)
public
initializer
{
Ownable.initialize(_nextOwner);
_setRate(_initialRate);
}
function setExchangeRate(uint256 _nextRate) public onlyOwner {
_setRate(_nextRate);
}
function exchangeRateCurrent() public view returns (uint256) {
require(_rate != 0, "ERC20WithRate: rate has not been initialized");
return _rate;
}
function _setRate(uint256 _nextRate) internal {
require(_nextRate > 0, "ERC20WithRate: rate must be greater than zero");
_rate = _nextRate;
}
function balanceOfUnderlying(address _account)
public
view
returns (uint256)
{
return toUnderlying(balanceOf(_account));
}
function toUnderlying(uint256 _amount) public view returns (uint256) {
return _amount.mul(_rate).div(_rateScale);
}
function fromUnderlying(uint256 _amountUnderlying)
public
view
returns (uint256)
{
return _amountUnderlying.mul(_rateScale).div(_rate);
}
}
contract ERC20WithPermit is Initializable, ERC20, ERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) public nonces;
string public version;
bytes32 public DOMAIN_SEPARATOR;
bytes32
public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
function initialize(
uint256 _chainId,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
version = _version;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes(version)),
_chainId,
address(this)
)
);
}
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed
)
)
)
);
require(holder != address(0), "ERC20WithRate: address must not be 0x0");
require(
holder == ecrecover(digest, v, r, s),
"ERC20WithRate: invalid signature"
);
require(
expiry == 0 || now <= expiry,
"ERC20WithRate: permit has expired"
);
require(nonce == nonces[holder]++, "ERC20WithRate: invalid nonce");
uint256 amount = allowed ? uint256(-1) : 0;
_approve(holder, spender, amount);
}
}
contract RenERC20LogicV1 is
Initializable,
ERC20,
ERC20Detailed,
ERC20WithRate,
ERC20WithPermit,
Claimable,
CanReclaimTokens
{
function initialize(
uint256 _chainId,
address _nextOwner,
uint256 _initialRate,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
ERC20WithRate.initialize(_nextOwner, _initialRate);
ERC20WithPermit.initialize(
_chainId,
_version,
_name,
_symbol,
_decimals
);
Claimable.initialize(_nextOwner);
CanReclaimTokens.initialize(_nextOwner);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transferFrom(sender, recipient, amount);
}
}
contract RenERC20Proxy is InitializableAdminUpgradeabilityProxy {
}
interface IMintGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
}
interface IBurnGateway {
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
interface IGateway {
function mint(
bytes32 _pHash,
uint256 _amount,
bytes32 _nHash,
bytes calldata _sig
) external returns (uint256);
function mintFee() external view returns (uint256);
function burn(bytes calldata _to, uint256 _amountScaled)
external
returns (uint256);
function burnFee() external view returns (uint256);
}
contract GatewayStateV1 {
uint256 constant BIPS_DENOMINATOR = 10000;
uint256 public minimumBurnAmount;
RenERC20LogicV1 public token;
address public mintAuthority;
address public feeRecipient;
uint16 public mintFee;
uint16 public burnFee;
mapping(bytes32 => bool) public status;
uint256 public nextN = 0;
}
contract GatewayStateV2 {
struct Burn {
uint256 _blocknumber;
bytes _to;
uint256 _amount;
string _chain;
bytes _payload;
}
mapping(uint256 => Burn) internal burns;
bytes32 public selectorHash;
}
contract MintGatewayLogicV1 is
Initializable,
Claimable,
CanReclaimTokens,
IGateway,
GatewayStateV1,
GatewayStateV2
{
using SafeMath for uint256;
event LogMintAuthorityUpdated(address indexed _newMintAuthority);
event LogMint(
address indexed _to,
uint256 _amount,
uint256 indexed _n,
bytes32 indexed _nHash
);
event LogBurn(
bytes _to,
uint256 _amount,
uint256 indexed _n,
bytes indexed _indexedTo
);
modifier onlyOwnerOrMintAuthority() {
require(
msg.sender == mintAuthority || msg.sender == owner(),
"MintGateway: caller is not the owner or mint authority"
);
_;
}
function initialize(
RenERC20LogicV1 _token,
address _feeRecipient,
address _mintAuthority,
uint16 _mintFee,
uint16 _burnFee,
uint256 _minimumBurnAmount
) public initializer {
Claimable.initialize(msg.sender);
CanReclaimTokens.initialize(msg.sender);
minimumBurnAmount = _minimumBurnAmount;
token = _token;
mintFee = _mintFee;
burnFee = _burnFee;
updateMintAuthority(_mintAuthority);
updateFeeRecipient(_feeRecipient);
}
function updateSelectorHash(bytes32 _selectorHash) public onlyOwner {
selectorHash = _selectorHash;
}
function claimTokenOwnership() public {
token.claimOwnership();
}
function transferTokenOwnership(MintGatewayLogicV1 _nextTokenOwner)
public
onlyOwner
{
token.transferOwnership(address(_nextTokenOwner));
_nextTokenOwner.claimTokenOwnership();
}
function updateMintAuthority(address _nextMintAuthority)
public
onlyOwnerOrMintAuthority
{
require(
_nextMintAuthority != address(0),
"MintGateway: mintAuthority cannot be set to address zero"
);
mintAuthority = _nextMintAuthority;
emit LogMintAuthorityUpdated(mintAuthority);
}
function updateMinimumBurnAmount(uint256 _minimumBurnAmount)
public
onlyOwner
{
minimumBurnAmount = _minimumBurnAmount;
}
function updateFeeRecipient(address _nextFeeRecipient) public onlyOwner {
require(
_nextFeeRecipient != address(0x0),
"MintGateway: fee recipient cannot be 0x0"
);
feeRecipient = _nextFeeRecipient;
}
function updateMintFee(uint16 _nextMintFee) public onlyOwner {
mintFee = _nextMintFee;
}
function updateBurnFee(uint16 _nextBurnFee) public onlyOwner {
burnFee = _nextBurnFee;
}
function mint(
bytes32 _pHash,
uint256 _amountUnderlying,
bytes32 _nHash,
bytes memory _sig
) public returns (uint256) {
bytes32 sigHash = hashForSignature(
_pHash,
_amountUnderlying,
msg.sender,
_nHash
);
require(
status[sigHash] == false,
"MintGateway: nonce hash already spent"
);
if (!verifySignature(sigHash, _sig)) {
revert(
String.add8(
"MintGateway: invalid signature. pHash: ",
String.fromBytes32(_pHash),
", amount: ",
String.fromUint(_amountUnderlying),
", msg.sender: ",
String.fromAddress(msg.sender),
", _nHash: ",
String.fromBytes32(_nHash)
)
);
}
status[sigHash] = true;
uint256 amountScaled = token.fromUnderlying(_amountUnderlying);
uint256 absoluteFeeScaled = amountScaled.mul(mintFee).div(
BIPS_DENOMINATOR
);
uint256 receivedAmountScaled = amountScaled.sub(
absoluteFeeScaled,
"MintGateway: fee exceeds amount"
);
token.mint(msg.sender, receivedAmountScaled);
token.mint(feeRecipient, absoluteFeeScaled);
uint256 receivedAmountUnderlying = token.toUnderlying(
receivedAmountScaled
);
emit LogMint(msg.sender, receivedAmountUnderlying, nextN, _nHash);
nextN += 1;
return receivedAmountScaled;
}
function burn(bytes memory _to, uint256 _amount) public returns (uint256) {
require(_to.length != 0, "MintGateway: to address is empty");
uint256 fee = _amount.mul(burnFee).div(BIPS_DENOMINATOR);
uint256 amountAfterFee = _amount.sub(
fee,
"MintGateway: fee exceeds amount"
);
uint256 amountAfterFeeUnderlying = token.toUnderlying(amountAfterFee);
token.burn(msg.sender, _amount);
token.mint(feeRecipient, fee);
require(
amountAfterFeeUnderlying > minimumBurnAmount,
"MintGateway: amount is less than the minimum burn amount"
);
emit LogBurn(_to, amountAfterFeeUnderlying, nextN, _to);
bytes memory payload;
GatewayStateV2.burns[nextN] = Burn({
_blocknumber: block.number,
_to: _to,
_amount: amountAfterFeeUnderlying,
_chain: "",
_payload: payload
});
nextN += 1;
return amountAfterFeeUnderlying;
}
function getBurn(uint256 _n)
public
view
returns (
uint256 _blocknumber,
bytes memory _to,
uint256 _amount,
string memory _chain,
bytes memory _payload
)
{
Burn memory burnStruct = GatewayStateV2.burns[_n];
require(burnStruct._to.length > 0, "MintGateway: burn not found");
return (
burnStruct._blocknumber,
burnStruct._to,
burnStruct._amount,
burnStruct._chain,
burnStruct._payload
);
}
function verifySignature(bytes32 _sigHash, bytes memory _sig)
public
view
returns (bool)
{
return mintAuthority == ECDSA.recover(_sigHash, _sig);
}
function hashForSignature(
bytes32 _pHash,
uint256 _amount,
address _to,
bytes32 _nHash
) public view returns (bytes32) {
return
keccak256(abi.encode(_pHash, _amount, selectorHash, _to, _nHash));
}
}
contract MintGatewayProxy is InitializableAdminUpgradeabilityProxy {
}File 6 of 6: RenERC20LogicV1
/**
Deployed by Ren Project, https://renproject.io
Commit hash: 1e106b3
Repository: https://github.com/renproject/gateway-sol
Issues: https://github.com/renproject/gateway-sol/issues
Licenses
@openzeppelin/contracts: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE
gateway-sol: https://github.com/renproject/gateway-sol/blob/master/LICENSE
*/
pragma solidity ^0.5.16;
contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
function isConstructor() private view returns (bool) {
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
uint256[50] private ______gap;
}
contract Context is Initializable {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
contract Proxy {
function () payable external {
_fallback();
}
function _implementation() internal view returns (address);
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize)
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch result
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
function _willFallback() internal {
}
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
library OpenZeppelinUpgradesAddress {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
contract BaseUpgradeabilityProxy is Proxy {
event Upgraded(address indexed implementation);
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _implementation() internal view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
function _setImplementation(address newImplementation) internal {
require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
}
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
constructor(address _logic, bytes memory _data) public payable {
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
event AdminChanged(address previousAdmin, address newAdmin);
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_fallback();
}
}
function admin() external ifAdmin returns (address) {
return _admin();
}
function implementation() external ifAdmin returns (address) {
return _implementation();
}
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeTo(newImplementation);
}
function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
_upgradeTo(newImplementation);
(bool success,) = newImplementation.delegatecall(data);
require(success);
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
function _willFallback() internal {
require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
super._willFallback();
}
}
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
function initialize(address _logic, bytes memory _data) public payable {
require(_implementation() == address(0));
assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
_setImplementation(_logic);
if(_data.length > 0) {
(bool success,) = _logic.delegatecall(_data);
require(success);
}
}
}
contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy {
function initialize(address _logic, address _admin, bytes memory _data) public payable {
require(_implementation() == address(0));
InitializableUpgradeabilityProxy.initialize(_logic, _data);
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
_setAdmin(_admin);
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contract ERC20 is Initializable, Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
uint256[50] private ______gap;
}
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
contract Claimable is Initializable, Ownable {
address public pendingOwner;
function initialize(address _nextOwner) public initializer {
Ownable.initialize(_nextOwner);
}
modifier onlyPendingOwner() {
require(
_msgSender() == pendingOwner,
"Claimable: caller is not the pending owner"
);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != owner() && newOwner != pendingOwner,
"Claimable: invalid new owner"
);
pendingOwner = newOwner;
}
function claimOwnership() public onlyPendingOwner {
_transferOwnership(pendingOwner);
delete pendingOwner;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract CanReclaimTokens is Claimable {
using SafeERC20 for ERC20;
mapping(address => bool) private recoverableTokensBlacklist;
function initialize(address _nextOwner) public initializer {
Claimable.initialize(_nextOwner);
}
function blacklistRecoverableToken(address _token) public onlyOwner {
recoverableTokensBlacklist[_token] = true;
}
function recoverTokens(address _token) external onlyOwner {
require(
!recoverableTokensBlacklist[_token],
"CanReclaimTokens: token is not recoverable"
);
if (_token == address(0x0)) {
msg.sender.transfer(address(this).balance);
} else {
ERC20(_token).safeTransfer(
msg.sender,
ERC20(_token).balanceOf(address(this))
);
}
}
}
contract ERC20WithRate is Initializable, Ownable, ERC20 {
using SafeMath for uint256;
uint256 public constant _rateScale = 1e18;
uint256 internal _rate;
event LogRateChanged(uint256 indexed _rate);
function initialize(address _nextOwner, uint256 _initialRate)
public
initializer
{
Ownable.initialize(_nextOwner);
_setRate(_initialRate);
}
function setExchangeRate(uint256 _nextRate) public onlyOwner {
_setRate(_nextRate);
}
function exchangeRateCurrent() public view returns (uint256) {
require(_rate != 0, "ERC20WithRate: rate has not been initialized");
return _rate;
}
function _setRate(uint256 _nextRate) internal {
require(_nextRate > 0, "ERC20WithRate: rate must be greater than zero");
_rate = _nextRate;
}
function balanceOfUnderlying(address _account)
public
view
returns (uint256)
{
return toUnderlying(balanceOf(_account));
}
function toUnderlying(uint256 _amount) public view returns (uint256) {
return _amount.mul(_rate).div(_rateScale);
}
function fromUnderlying(uint256 _amountUnderlying)
public
view
returns (uint256)
{
return _amountUnderlying.mul(_rateScale).div(_rate);
}
}
contract ERC20WithPermit is Initializable, ERC20, ERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) public nonces;
string public version;
bytes32 public DOMAIN_SEPARATOR;
bytes32
public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
function initialize(
uint256 _chainId,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
version = _version;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes(version)),
_chainId,
address(this)
)
);
}
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed
)
)
)
);
require(holder != address(0), "ERC20WithRate: address must not be 0x0");
require(
holder == ecrecover(digest, v, r, s),
"ERC20WithRate: invalid signature"
);
require(
expiry == 0 || now <= expiry,
"ERC20WithRate: permit has expired"
);
require(nonce == nonces[holder]++, "ERC20WithRate: invalid nonce");
uint256 amount = allowed ? uint256(-1) : 0;
_approve(holder, spender, amount);
}
}
contract RenERC20LogicV1 is
Initializable,
ERC20,
ERC20Detailed,
ERC20WithRate,
ERC20WithPermit,
Claimable,
CanReclaimTokens
{
function initialize(
uint256 _chainId,
address _nextOwner,
uint256 _initialRate,
string memory _version,
string memory _name,
string memory _symbol,
uint8 _decimals
) public initializer {
ERC20Detailed.initialize(_name, _symbol, _decimals);
ERC20WithRate.initialize(_nextOwner, _initialRate);
ERC20WithPermit.initialize(
_chainId,
_version,
_name,
_symbol,
_decimals
);
Claimable.initialize(_nextOwner);
CanReclaimTokens.initialize(_nextOwner);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transfer(recipient, amount);
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(
recipient != address(this),
"RenERC20: can't transfer to token address"
);
return super.transferFrom(sender, recipient, amount);
}
}
contract RenERC20Proxy is InitializableAdminUpgradeabilityProxy {
}