3
3
pragma solidity ^ 0.8.0 ;
4
4
import "./Auth.sol " ;
5
5
import "./StellarAsset.sol " ;
6
+ import "@openzeppelin/contracts/security/ReentrancyGuard.sol " ;
6
7
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol " ;
7
8
import "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
9
+ import "@openzeppelin/contracts/utils/math/SafeMath.sol " ;
8
10
9
11
// Every bridge transfer has a globally unique id.
10
12
//
@@ -80,7 +82,7 @@ bytes32 constant WITHDRAW_ETH_ID = keccak256("withdrawETH");
80
82
// WITHDRAW_ERC20_ID is used to distinguish withdrawERC20() signatures from signatures for other bridge functions.
81
83
bytes32 constant WITHDRAW_ERC20_ID = keccak256 ("withdrawERC20 " );
82
84
83
- contract Bridge is Auth {
85
+ contract Bridge is Auth , ReentrancyGuard {
84
86
// paused is a bitmask which determines whether deposits / withdrawals are enabled on the bridge
85
87
uint8 public paused;
86
88
// SetPaused is emitted whenever the paused state of the bridge changes
@@ -134,7 +136,7 @@ contract Bridge is Auth {
134
136
address token ,
135
137
uint256 destination ,
136
138
uint256 amount
137
- ) external {
139
+ ) external nonReentrant {
138
140
require ((paused & PAUSE_DEPOSITS) == 0 , "deposits are paused " );
139
141
require (amount > 0 , "deposit amount is zero " );
140
142
require (token != address (0x0 ), "invalid token address " );
@@ -145,12 +147,16 @@ contract Bridge is Auth {
145
147
if (isStellarAsset[token]) {
146
148
StellarAsset (token).burn (msg .sender , amount);
147
149
} else {
150
+ IERC20 tokenContract = IERC20 (token);
151
+ uint256 before = tokenContract.balanceOf (address (this ));
148
152
SafeERC20.safeTransferFrom (
149
- IERC20 (token) ,
153
+ tokenContract ,
150
154
msg .sender ,
151
155
address (this ),
152
156
amount
153
157
);
158
+ uint256 received = SafeMath.sub (tokenContract.balanceOf (address (this )), before);
159
+ require (amount == received, "received amount not equal to expected amount " );
154
160
}
155
161
}
156
162
0 commit comments