Skip to content

Commit a55aa4b

Browse files
block.number -> block.timestamp
tweak timing tests make tests even better
1 parent 5ea4c93 commit a55aa4b

File tree

4 files changed

+23
-25
lines changed

4 files changed

+23
-25
lines changed

contracts/UniswapV2Exchange.sol

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ contract UniswapV2Exchange is IUniswapV2Exchange, UniswapV2ERC20 {
1616
address public token0;
1717
address public token1;
1818

19-
uint112 private reserve0; // single storage slot, (jointly) access via getReserves
20-
uint112 private reserve1; // single storage slot, (jointly) access via getReserves
21-
uint32 private blockNumberLast; // single storage slot, (jointly) access via getReserves
19+
uint112 private reserve0; // single storage slot, (jointly) access via getReserves
20+
uint112 private reserve1; // single storage slot, (jointly) access via getReserves
21+
uint32 private blockTimestampLast; // single storage slot, (jointly) access via getReserves
2222

2323
uint public price0CumulativeLast;
2424
uint public price1CumulativeLast;
@@ -52,25 +52,25 @@ contract UniswapV2Exchange is IUniswapV2Exchange, UniswapV2ERC20 {
5252
token1 = _token1;
5353
}
5454

55-
function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockNumberLast) {
55+
function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
5656
_reserve0 = reserve0;
5757
_reserve1 = reserve1;
58-
_blockNumberLast = blockNumberLast;
58+
_blockTimestampLast = blockTimestampLast;
5959
}
6060

6161
// update reserves and, on the first time this function is called per block, price accumulators
6262
function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
6363
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), "UniswapV2: BALANCE_OVERFLOW");
64-
uint32 blockNumber = uint32(block.number % 2**32);
65-
uint32 blocksElapsed = blockNumber - blockNumberLast; // overflow is desired
66-
if (blocksElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
64+
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
65+
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
66+
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
6767
// * never overflows, and + overflow is desired
68-
price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * blocksElapsed;
69-
price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * blocksElapsed;
68+
price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
69+
price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
7070
}
7171
reserve0 = uint112(balance0);
7272
reserve1 = uint112(balance1);
73-
blockNumberLast = blockNumber;
73+
blockTimestampLast = blockTimestamp;
7474
emit Sync(reserve0, reserve1);
7575
}
7676

contracts/interfaces/IUniswapV2Exchange.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface IUniswapV2Exchange {
1010
function factory() external view returns (address);
1111
function token0() external view returns (address);
1212
function token1() external view returns (address);
13-
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockNumberLast);
13+
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
1414
function price0CumulativeLast() external view returns (uint);
1515
function price1CumulativeLast() external view returns (uint);
1616

test/UniswapV2Exchange.spec.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Contract } from 'ethers'
33
import { solidity, MockProvider, createFixtureLoader } from 'ethereum-waffle'
44
import { BigNumber, bigNumberify } from 'ethers/utils'
55

6-
import { expandTo18Decimals, mineBlocks } from './shared/utilities'
6+
import { expandTo18Decimals, mineBlock } from './shared/utilities'
77
import { exchangeFixture } from './shared/fixtures'
88
import { AddressZero } from 'ethers/constants'
99

@@ -142,11 +142,13 @@ describe('UniswapV2Exchange', () => {
142142
await addLiquidity(token0Amount, token1Amount)
143143

144144
// ensure that setting price{0,1}CumulativeLast for the first time doesn't affect our gas math
145+
await mineBlock(provider, 1)
145146
await exchange.sync(overrides)
146147

147148
const swapAmount = expandTo18Decimals(1)
148149
const expectedOutputAmount = bigNumberify('453305446940074565')
149150
await token0.transfer(exchange.address, swapAmount)
151+
await mineBlock(provider, 1)
150152
const gasCost = await exchange.estimate.swap(token0.address, expectedOutputAmount, wallet.address, overrides)
151153
console.log(`Gas required for swap: ${gasCost}`)
152154
})
@@ -182,16 +184,17 @@ describe('UniswapV2Exchange', () => {
182184
const token1Amount = expandTo18Decimals(3)
183185
await addLiquidity(token0Amount, token1Amount)
184186

185-
const blockNumber = (await exchange.getReserves())[2]
187+
const blockTimestamp = (await exchange.getReserves())[2]
186188
expect(await exchange.price0CumulativeLast()).to.eq(0)
187189
expect(await exchange.price1CumulativeLast()).to.eq(0)
188190

191+
await mineBlock(provider, 1)
189192
await exchange.sync(overrides)
190193
expect(await exchange.price0CumulativeLast()).to.eq(bigNumberify(2).pow(112))
191194
expect(await exchange.price1CumulativeLast()).to.eq(bigNumberify(2).pow(112))
192-
expect((await exchange.getReserves())[2]).to.eq(blockNumber + 1)
195+
expect((await exchange.getReserves())[2]).to.eq(blockTimestamp + 1)
193196

194-
await mineBlocks(provider, 8)
197+
await mineBlock(provider, 9)
195198
await exchange.sync(overrides)
196199
expect(await exchange.price0CumulativeLast()).to.eq(
197200
bigNumberify(2)
@@ -203,6 +206,6 @@ describe('UniswapV2Exchange', () => {
203206
.pow(112)
204207
.mul(10)
205208
)
206-
expect((await exchange.getReserves())[2]).to.eq(blockNumber + 10)
209+
expect((await exchange.getReserves())[2]).to.eq(blockTimestamp + 10)
207210
})
208211
})

test/shared/utilities.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ export async function getApprovalDigest(
7979
)
8080
}
8181

82-
async function mineBlock(provider: Web3Provider, timestamp?: number): Promise<void> {
83-
await new Promise((resolve, reject) => {
82+
export async function mineBlock(provider: Web3Provider, seconds: number): Promise<void> {
83+
await new Promise(async (resolve, reject) => {
8484
;(provider._web3Provider.sendAsync as any)(
85-
{ jsonrpc: '2.0', method: 'evm_mine', params: timestamp ? [timestamp] : [] },
85+
{ jsonrpc: '2.0', method: 'evm_mine', params: [(await provider.getBlock('latest')).timestamp + seconds] },
8686
(error: any, result: any): void => {
8787
if (error) {
8888
reject(error)
@@ -93,8 +93,3 @@ async function mineBlock(provider: Web3Provider, timestamp?: number): Promise<vo
9393
)
9494
})
9595
}
96-
97-
export async function mineBlocks(provider: Web3Provider, numberOfBlocks: number, timestamp?: number): Promise<void> {
98-
await Promise.all([...Array(numberOfBlocks - 1)].map(() => mineBlock(provider)))
99-
await mineBlock(provider, timestamp)
100-
}

0 commit comments

Comments
 (0)