Lachain ERC20 handler
Contract
1
// pragma solidity 0.6.4;
2
pragma experimental ABIEncoderV2;
3
import "../interfaces/IDepositExecute.sol";
4
import "../interfaces/IERC20.sol";
5
import "./HandlerHelpers.sol";
6
import "../ERC20Safe.sol";
7
import "../ExampleToken.sol";
8
import "../utils/UpgradableOwnable.sol";
9
/**
10
@title Handles ERC20 deposits and deposit executions.
11
@notice This contract is intended to be used with the Bridge contract.
12
*/
13
contract ERC20Handler is
14
IDepositExecute,
15
HandlerHelpers,
16
UpgradableOwnable,
17
ERC20Safe
18
{
19
struct DepositRecord {
20
address _tokenAddress;
21
bytes8 _destinationChainID;
22
bytes32 _resourceID;
23
address _destinationRecipientAddress;
24
address _depositer;
25
uint256 _amount;
26
}
27
// depositNonce => Deposit Record
28
mapping(bytes8 => mapping(uint64 => DepositRecord)) public _depositRecords;
29
/**
30
@param bridgeAddress Contract address of previously deployed Bridge.
31
*/
32
function initialize(address bridgeAddress) public {
33
_bridgeAddress = bridgeAddress;
34
ownableInit(msg.sender);
35
}
36
function adminChangeBridgeAddress(address newBridgeAddress)
37
external
38
onlyOwner
39
isInitisalised
40
{
41
_bridgeAddress = newBridgeAddress;
42
}
43
/**
44
@param depositNonce This ID will have been generated by the Bridge contract.
45
@param destId ID of chain deposit will be bridged to.
46
@return DepositRecord which consists of:
47
- _tokenAddress Address used when {deposit} was executed.
48
- _destinationChainID ChainID deposited tokens are intended to end up on.
49
- _resourceID ResourceID used when {deposit} was executed.
50
- _destinationRecipientAddress Address tokens are intended to be deposited to on desitnation chain.
51
- _depositer Address that initially called {deposit} in the Bridge contract.
52
- _amount Amount of tokens that were deposited.
53
*/
54
function getDepositRecord(uint64 depositNonce, bytes8 destId)
55
external
56
view
57
isInitisalised
58
returns (DepositRecord memory)
59
{
60
return _depositRecords[destId][depositNonce];
61
}
62
/**
63
@notice A deposit is initiatied by making a deposit in the Bridge contract.
64
@param destinationChainID Chain ID of chain tokens are expected to be bridged to.
65
@param depositNonce This value is generated as an ID by the Bridge contract.
66
@param depositer Address of account making the deposit in the Bridge contract.
67
@notice Data passed into the function should be constructed as follows:
68
amount uint256 bytes 0 - 32
69
recipientAddress length uint256 bytes 32 - 64
70
recipientAddress bytes bytes 64 - END
71
@dev Depending if the corresponding {tokenAddress} for the parsed {resourceID} is
72
marked true in {_burnList}, deposited tokens will be burned, if not, they will be locked.
73
*/
74
function deposit(
75
bytes32 resourceID,
76
bytes8 destinationChainID,
77
uint64 depositNonce,
78
address depositer,
79
address recipientAddress,
80
uint256 amount,
81
bytes calldata params
82
) external override onlyBridge isInitisalised returns (address) {
83
// bytes memory recipientAddress;
84
// uint256 amount;
85
// uint256 lenRecipientAddress;
86
// assembly {
87
// amount := calldataload(0xC4)
88
// recipientAddress := mload(0x40)
89
// lenRecipientAddress := calldataload(0xE4)
90
// mstore(0x40, add(0x20, add(recipientAddress, lenRecipientAddress)))
91
// calldatacopy(
92
// recipientAddress, // copy to destinationRecipientAddress
93
// 0xE4, // copy from calldata @ 0x104
94
// sub(calldatasize(), 0xE) // copy size (calldatasize - 0x104)
95
// )
96
// }
97
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
98
require(
99
_contractWhitelist[tokenAddress],
100
"provided tokenAddress is not whitelisted"
101
);
102
if (_burnList[tokenAddress]) {
103
burnERC20(tokenAddress, depositer, amount);
104
} else {
105
lockERC20(tokenAddress, depositer, address(this), amount);
106
}
107
_depositRecords[destinationChainID][depositNonce] = DepositRecord(
108
tokenAddress,
109
destinationChainID,
110
resourceID,
111
recipientAddress,
112
depositer,
113
amount
114
);
115
return (tokenAddress);
116
}
117
/**
118
@notice Proposal execution should be initiated when a proposal is finalized in the Bridge contract.
119
by a relayer on the deposit's destination chain.
120
@notice Data passed into the function should be constructed as follows:
121
amount uint256 bytes 0 - 32
122
destinationRecipientAddress length uint256 bytes 32 - 64
123
destinationRecipientAddress bytes bytes 64 - END
124
*/
125
function executeProposal(
126
bytes32 resourceID,
127
address recipientAddress,
128
uint256 amount,
129
bytes calldata params
130
) external override onlyBridge isInitisalised {
131
// uint256 amount;
132
// bytes memory destinationRecipientAddress;
133
// assembly {
134
// amount := calldataload(0x64)
135
// destinationRecipientAddress := mload(0x40)
136
// let lenDestinationRecipientAddress := calldataload(0x84)
137
// mstore(
138
// 0x40,
139
// add(
140
// 0x20,
141
// add(
142
// destinationRecipientAddress,
143
// lenDestinationRecipientAddress
144
// )
145
// )
146
// )
147
// // in the calldata the destinationRecipientAddress is stored at 0xC4 after accounting for the function signature and length declaration
148
// calldatacopy(
149
// destinationRecipientAddress, // copy to destinationRecipientAddress
150
// 0x84, // copy from calldata @ 0x84
151
// sub(calldatasize(), 0x84) // copy size to the end of calldata
152
// )
153
// }
154
// bytes20 recipientAddress;
155
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
156
// assembly {
157
// recipientAddress := mload(add(destinationRecipientAddress, 0x20))
158
// }
159
require(
160
_contractWhitelist[tokenAddress],
161
"provided tokenAddress is not whitelisted"
162
);
163
if (_burnList[tokenAddress]) {
164
mintERC20(tokenAddress, recipientAddress, amount);
165
} else {
166
releaseERC20(tokenAddress, recipientAddress, amount);
167
}
168
}
169
/**
170
@notice Used to manually release ERC20 tokens from ERC20Safe.
171
@param tokenAddress Address of token contract to release.
172
@param recipient Address to release tokens to.
173
@param amount The amount of ERC20 tokens to release.
174
*/
175
function withdraw(
176
address tokenAddress,
177
address recipient,
178
uint256 amount
179
) external override onlyBridge isInitisalised {
180
releaseERC20(tokenAddress, recipient, amount);
181
}
182
function getAddressFromResourceId(bytes32 resourceID)
183
external
184
view
185
override
186
returns (address)
187
{
188
return _resourceIDToTokenContractAddress[resourceID];
189
}
190
/**
191
@notice Used to approve spending tokens.
192
@param resourceID ResourceID to be used for approval.
193
@param spender Spender address.
194
@param amount Amount to approve.
195
*/
196
function approve(
197
bytes32 resourceID,
198
address spender,
199
uint256 amount
200
) external override onlyBridge isInitisalised {
201
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
202
require(
203
_contractWhitelist[tokenAddress],
204
"provided tokenAddress is not whitelisted"
205
);
206
approveERC20(tokenAddress, spender, amount);
207
}
208
}
Copied!
Copy link