@hyperlane-xyz/core
Version:
Core solidity contracts for Hyperlane
143 lines (124 loc) • 5.28 kB
text/typescript
import { getUsers, Personas } from '../test-helpers/setup'
import { ethers } from 'hardhat'
import { Signer } from 'ethers'
import {
HeartbeatRequester,
MockAggregatorProxy,
MockOffchainAggregator,
} from '../../typechain'
import { HeartbeatRequester__factory as HeartbeatRequesterFactory } from '../../typechain/factories/HeartbeatRequester__factory'
import { MockAggregatorProxy__factory as MockAggregatorProxyFactory } from '../../typechain/factories/MockAggregatorProxy__factory'
import { MockOffchainAggregator__factory as MockOffchainAggregatorFactory } from '../../typechain/factories/MockOffchainAggregator__factory'
import { assert, expect } from 'chai'
let personas: Personas
let owner: Signer
let caller1: Signer
let proxy1: Signer
let proxy2: Signer
let aggregator: MockOffchainAggregator
let aggregatorFactory: MockOffchainAggregatorFactory
let aggregatorProxy: MockAggregatorProxy
let aggregatorProxyFactory: MockAggregatorProxyFactory
let requester: HeartbeatRequester
let requesterFactory: HeartbeatRequesterFactory
describe('HeartbeatRequester', () => {
beforeEach(async () => {
personas = (await getUsers()).personas
owner = personas.Default
caller1 = personas.Carol
proxy1 = personas.Nelly
proxy2 = personas.Eddy
// deploy heartbeat requester
requesterFactory = await ethers.getContractFactory('HeartbeatRequester')
requester = await requesterFactory.connect(owner).deploy()
await requester.deployed()
})
describe('#permitHeartbeat', () => {
it('adds a heartbeat and emits an event', async () => {
const callerAddress = await caller1.getAddress()
const proxyAddress1 = await proxy1.getAddress()
const proxyAddress2 = await proxy2.getAddress()
const tx1 = await requester
.connect(owner)
.permitHeartbeat(callerAddress, proxyAddress1)
await expect(tx1)
.to.emit(requester, 'HeartbeatPermitted')
.withArgs(callerAddress, proxyAddress1, ethers.constants.AddressZero)
const tx2 = await requester
.connect(owner)
.permitHeartbeat(callerAddress, proxyAddress2)
await expect(tx2)
.to.emit(requester, 'HeartbeatPermitted')
.withArgs(callerAddress, proxyAddress2, proxyAddress1)
})
it('reverts when not called by its owner', async () => {
const callerAddress = await caller1.getAddress()
const proxyAddress = await proxy1.getAddress()
await expect(
requester.connect(caller1).permitHeartbeat(callerAddress, proxyAddress),
).to.be.revertedWith('Only callable by owner')
})
})
describe('#removeHeartbeat', () => {
it('removes a heartbeat and emits an event', async () => {
const callerAddress = await caller1.getAddress()
const proxyAddress = await proxy1.getAddress()
const tx1 = await requester
.connect(owner)
.permitHeartbeat(callerAddress, proxyAddress)
await expect(tx1)
.to.emit(requester, 'HeartbeatPermitted')
.withArgs(callerAddress, proxyAddress, ethers.constants.AddressZero)
const tx2 = await requester.connect(owner).removeHeartbeat(callerAddress)
await expect(tx2)
.to.emit(requester, 'HeartbeatRemoved')
.withArgs(callerAddress, proxyAddress)
})
it('reverts when not called by its owner', async () => {
await expect(
requester.connect(caller1).removeHeartbeat(await caller1.getAddress()),
).to.be.revertedWith('Only callable by owner')
})
})
describe('#getAggregatorAndRequestHeartbeat', () => {
it('reverts if caller and proxy combination is not allowed', async () => {
const callerAddress = await caller1.getAddress()
const proxyAddress = await proxy1.getAddress()
await requester
.connect(owner)
.permitHeartbeat(callerAddress, proxyAddress)
await expect(
requester
.connect(caller1)
.getAggregatorAndRequestHeartbeat(await owner.getAddress()),
).to.be.revertedWithCustomError(requester, 'HeartbeatNotPermitted')
})
it('calls corresponding aggregator to request a new round', async () => {
aggregatorFactory = await ethers.getContractFactory(
'MockOffchainAggregator',
)
aggregator = await aggregatorFactory.connect(owner).deploy()
await aggregator.deployed()
aggregatorProxyFactory = await ethers.getContractFactory(
'MockAggregatorProxy',
)
aggregatorProxy = await aggregatorProxyFactory
.connect(owner)
.deploy(aggregator.address)
await aggregatorProxy.deployed()
await requester
.connect(owner)
.permitHeartbeat(await caller1.getAddress(), aggregatorProxy.address)
const tx1 = await requester
.connect(caller1)
.getAggregatorAndRequestHeartbeat(aggregatorProxy.address)
await expect(tx1).to.emit(aggregator, 'RoundIdUpdated').withArgs(1)
assert.equal((await aggregator.roundId()).toNumber(), 1)
const tx2 = await requester
.connect(caller1)
.getAggregatorAndRequestHeartbeat(aggregatorProxy.address)
await expect(tx2).to.emit(aggregator, 'RoundIdUpdated').withArgs(2)
assert.equal((await aggregator.roundId()).toNumber(), 2)
})
})
})