Skip to content

Commit 9d4e6b7

Browse files
authored
Fix for etherwrapper rounding/precision issue (#1261)
* wip fix for etherwrapper rounding issues * wip: maybe a fix? * precision test is failing correctly * fix precision issue * refactor: simplify calculation
1 parent 6fb8a7a commit 9d4e6b7

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

contracts/EtherWrapper.sol

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,12 @@ contract EtherWrapper is Owned, Pausable, MixinResolver, MixinSystemSettings, IE
166166
require(reserves > 0, "Contract cannot burn sETH for WETH, WETH balance is zero");
167167

168168
// principal = [amountIn / (1 + burnFeeRate)]
169-
uint principal = amountIn.divideDecimal(SafeDecimalMath.unit().add(burnFeeRate()));
169+
uint principal = amountIn.divideDecimalRound(SafeDecimalMath.unit().add(burnFeeRate()));
170170

171171
if (principal < reserves) {
172-
_burn(principal);
172+
_burn(principal, amountIn);
173173
} else {
174-
_burn(reserves);
174+
_burn(reserves, reserves.add(calculateBurnFee(reserves)));
175175
}
176176
}
177177

@@ -227,10 +227,9 @@ contract EtherWrapper is Owned, Pausable, MixinResolver, MixinSystemSettings, IE
227227
emit Minted(msg.sender, principal, feeAmountEth, amountIn);
228228
}
229229

230-
function _burn(uint principal) internal {
230+
function _burn(uint principal, uint amountIn) internal {
231231
// for burn, amount is inclusive of the fee.
232-
uint feeAmountEth = calculateBurnFee(principal);
233-
uint amountIn = principal.add(feeAmountEth);
232+
uint feeAmountEth = amountIn.sub(principal);
234233

235234
require(amountIn <= IERC20(address(synthsETH())).allowance(msg.sender, address(this)), "Allowance not high enough");
236235
require(amountIn <= IERC20(address(synthsETH())).balanceOf(msg.sender), "Balance is too low");

test/contracts/EtherWrapper.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,37 @@ contract('EtherWrapper', async accounts => {
482482
assert.equal(await etherWrapper.getReserves(), '0');
483483
});
484484
});
485+
486+
describe('precision and rounding', async () => {
487+
let burnAmount;
488+
let burnTx;
489+
490+
before(async () => {
491+
const amount = toUnit('1.2');
492+
await weth.deposit({ from: account1, value: amount });
493+
await weth.approve(etherWrapper.address, amount, { from: account1 });
494+
await etherWrapper.mint(amount, { from: account1 });
495+
496+
burnAmount = toUnit('0.9');
497+
await sETHSynth.issue(account1, burnAmount);
498+
await sETHSynth.approve(etherWrapper.address, burnAmount, { from: account1 });
499+
burnTx = await etherWrapper.burn(burnAmount, { from: account1 });
500+
});
501+
it('emits a Burn event which burns 0.9 sETH', async () => {
502+
const logs = await getDecodedLogs({
503+
hash: burnTx.tx,
504+
contracts: [sETHSynth],
505+
});
506+
507+
decodedEventEqual({
508+
event: 'Burned',
509+
emittedFrom: sETHSynth.address,
510+
args: [account1, burnAmount],
511+
log: logs.filter(l => !!l).find(({ name }) => name === 'Burned'),
512+
bnCloseVariance: 0,
513+
});
514+
});
515+
});
485516
});
486517
});
487518

0 commit comments

Comments
 (0)