Skip to content

Commit 8221d57

Browse files
authored
Merge pull request #53 from ampleforth/flashloan-protection
Added tx_origin check
2 parents 2f864a7 + a5e2552 commit 8221d57

File tree

8 files changed

+64
-28
lines changed

8 files changed

+64
-28
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.6.12;
3+
4+
import "../_interfaces/IXCAmpleController.sol";
5+
6+
contract MockConstructorRebaseCallerContract {
7+
constructor(address policy) public {
8+
// Take out a flash loan.
9+
// Do something funky...
10+
IXCAmpleController(policy).rebase(); // should fail
11+
// pay back flash loan.
12+
}
13+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.6.12;
3+
4+
import "../_interfaces/IXCAmpleController.sol";
5+
6+
contract MockRebaseCallerContract {
7+
function callRebase(address policy) public returns (bool) {
8+
// Take out a flash loan.
9+
// Do something funky...
10+
IXCAmpleController(policy).rebase(); // should fail
11+
// pay back flash loan.
12+
return true;
13+
}
14+
}

contracts/satellite-chain/xc-ampleforth/XCAmpleController.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ contract XCAmpleController is OwnableUpgradeable {
172172
* on the rebase relayer.
173173
*/
174174
function rebase() external {
175+
require(msg.sender == tx.origin, "XCAmpleController: expected caller to be eoa");
176+
175177
// recently reported epoch needs to be more than current globalEpoch in storage
176178
require(
177179
nextGlobalAmpleforthEpoch > globalAmpleforthEpoch,

helpers/deploy.js

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,7 @@ async function deployChainBridgeContracts(
211211
};
212212
}
213213

214-
async function deployTokenVault(
215-
ethers,
216-
deployer,
217-
txParams = {}) {
214+
async function deployTokenVault(ethers, deployer, txParams = {}) {
218215
const tokenVault = await deployContract(
219216
ethers,
220217
'TokenVault',
@@ -255,7 +252,7 @@ async function deployChainBridgeBaseChainGatewayContracts(
255252
rebaseGateway,
256253
);
257254

258-
if(isAdmin){
255+
if (isAdmin) {
259256
await (
260257
await bridge
261258
.connect(deployer)
@@ -281,7 +278,7 @@ async function deployChainBridgeBaseChainGatewayContracts(
281278
}
282279

283280
const transferFnSig = CB_FUNCTION_SIG_baseChainTransfer(transferGateway);
284-
if(isAdmin) {
281+
if (isAdmin) {
285282
await (
286283
await bridge
287284
.connect(deployer)
@@ -306,7 +303,7 @@ async function deployChainBridgeBaseChainGatewayContracts(
306303
]);
307304
}
308305

309-
if(await tokenVault.owner() == deployerAddress){
306+
if ((await tokenVault.owner()) == deployerAddress) {
310307
await (
311308
await tokenVault
312309
.connect(deployer)
@@ -317,9 +314,7 @@ async function deployChainBridgeBaseChainGatewayContracts(
317314
'Failed to add whitelist transfer gateway to vault as deployer not vault owner',
318315
);
319316
console.log('Execute the following on-chain');
320-
console.log('addBridgeGateway', [
321-
transferGateway.address,
322-
]);
317+
console.log('addBridgeGateway', [transferGateway.address]);
323318
}
324319

325320
return { rebaseGateway, transferGateway };
@@ -364,7 +359,7 @@ async function deployChainBridgeSatelliteChainGatewayContracts(
364359
const reportRebaseFnSig = CB_FUNCTION_SIG_satelliteChainReportRebase(
365360
rebaseGateway,
366361
);
367-
if(isAdmin) {
362+
if (isAdmin) {
368363
await (
369364
await bridge.adminSetGenericResource(
370365
genericHandler.address,
@@ -388,7 +383,7 @@ async function deployChainBridgeSatelliteChainGatewayContracts(
388383
}
389384

390385
const transferFnSig = CB_FUNCTION_SIG_satelliteChainTransfer(transferGateway);
391-
if(isAdmin) {
386+
if (isAdmin) {
392387
await (
393388
await bridge.adminSetGenericResource(
394389
genericHandler.address,

tasks/deploy/ampleforth.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ txTask('deploy:ampleforth_xc', 'Deploy cross chain ampleforth contract suite')
221221
);
222222
});
223223

224-
225224
txTask('deploy:token_vault', 'Deploy the token vault contract on base chain')
226225
.addParam('bridge', 'The bridge which secures the vault')
227226
.setAction(async (args, hre) => {
@@ -239,11 +238,7 @@ txTask('deploy:token_vault', 'Deploy the token vault contract on base chain')
239238

240239
console.log('------------------------------------------------------------');
241240
console.log('Deploying TokenVault on base chain');
242-
const tokenVault = await deployTokenVault(
243-
hre.ethers,
244-
deployer,
245-
txParams,
246-
);
241+
const tokenVault = await deployTokenVault(hre.ethers, deployer, txParams);
247242

248243
console.log('------------------------------------------------------------');
249244
console.log('Writing data to file');

tasks/deploy/chain_bridge.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
const {
32
types,
43
task,
@@ -72,10 +71,7 @@ cbDeployTask(
7271
console.log('Deployer:', deployerAddress);
7372
console.log(txParams);
7473

75-
let bridge,
76-
genericHandler,
77-
erc20Handler,
78-
erc721Handler;
74+
let bridge, genericHandler, erc20Handler, erc721Handler;
7975

8076
if (args.useDeployed) {
8177
console.log('Using deployed bridge');
@@ -89,7 +85,6 @@ cbDeployTask(
8985
'chainBridge/genericHandler',
9086
hre.ethers.provider,
9187
);
92-
9388
} else {
9489
const chainBridge = await deployChainBridgeContracts(
9590
args,

test/integration/chain_bridge.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,10 +571,7 @@ describe('Transfers scenarios', function () {
571571
it('should revert', async function () {
572572
await baseChainAmplContracts.ampl
573573
.connect(userBBaseChainWallet)
574-
.approve(
575-
baseChainAmplContracts.tokenVault.address,
576-
toAmplFixedPt('0'),
577-
);
574+
.approve(baseChainAmplContracts.tokenVault.address, toAmplFixedPt('0'));
578575
await expect(
579576
execXCSend(
580577
'base',

test/unit/satellite-chain/xc-ampleforth/xc_controller_rebase.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,31 @@ describe('XCAmpleController:rebase:epoch', async () => {
6969
});
7070
});
7171

72+
describe('XCAmpleController:rebase:called by a contract', function () {
73+
it('should fail', async function () {
74+
await controller.connect(bridge).reportRebase(2, 1000);
75+
const rebaseCallerContract = await (
76+
await ethers.getContractFactory('MockRebaseCallerContract')
77+
)
78+
.connect(deployer)
79+
.deploy();
80+
await expect(
81+
rebaseCallerContract.callRebase(controller.address),
82+
).to.be.revertedWith('XCAmpleController: expected caller to be eoa');
83+
});
84+
});
85+
86+
describe('XCAmpleController:rebase:called by a contract which is being constructed', function () {
87+
it('should fail', async function () {
88+
await controller.connect(bridge).reportRebase(2, 1000);
89+
await expect(
90+
(await ethers.getContractFactory('MockConstructorRebaseCallerContract'))
91+
.connect(deployer)
92+
.deploy(controller.address),
93+
).to.be.revertedWith('XCAmpleController: expected caller to be eoa');
94+
});
95+
});
96+
7297
describe('XCAmpleController:rebase', async () => {
7398
beforeEach('setup XCAmpleController contract', async () => {
7499
await setupContracts();

0 commit comments

Comments
 (0)