Skip to content

Commit

Permalink
Format TS + Solidity source, fix test
Browse files Browse the repository at this point in the history
  • Loading branch information
krebernisak committed Aug 25, 2022
1 parent dd0dd18 commit e7727e3
Show file tree
Hide file tree
Showing 56 changed files with 1,121 additions and 774 deletions.
18 changes: 16 additions & 2 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 120,
"printWidth": 100,
"endOfLine": "auto",
"trailingComma": "all"
"tabWidth": 2,
"trailingComma": "all",
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ namespace sequencer_uptime_feed:

simple_read_access_controller.initialize(owner_address)

let round_id = 1
let (timestamp) = get_block_timestamp()
_record_round(1, initial_status, timestamp)
_record_round(round_id, initial_status, timestamp)

return ()
end
Expand All @@ -127,8 +128,8 @@ namespace sequencer_uptime_feed:
if latest_status == status:
_update_round(latest_round_id, status)
else:
let latest_round_id = latest_round_id + 1
_record_round(latest_round_id, status, timestamp)
let round_id = latest_round_id + 1
_record_round(round_id, status, timestamp)
end

return ()
Expand Down
133 changes: 66 additions & 67 deletions contracts/contracts/solidity/emergency/StarkNetValidator.sol
Original file line number Diff line number Diff line change
@@ -1,89 +1,88 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@chainlink/contracts/src/v0.8/interfaces/AggregatorValidatorInterface.sol';
import '@chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol';
import '@chainlink/contracts/src/v0.8/interfaces/AccessControllerInterface.sol';
import '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';
import '@chainlink/contracts/src/v0.8/SimpleWriteAccessController.sol';
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorValidatorInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AccessControllerInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@chainlink/contracts/src/v0.8/SimpleWriteAccessController.sol";

import '@chainlink/contracts/src/v0.8/dev/vendor/openzeppelin-solidity/v4.3.1/contracts/utils/Address.sol';
import "@chainlink/contracts/src/v0.8/dev/vendor/openzeppelin-solidity/v4.3.1/contracts/utils/Address.sol";

import '../../../vendor/starkware-libs/starkgate-contracts-solidity-v0.8/contracts/starkware/starknet/solidity/IStarknetMessaging.sol';
import "../../../vendor/starkware-libs/starkgate-contracts-solidity-v0.8/contracts/starkware/starknet/solidity/IStarknetMessaging.sol";

/**
* @title StarkNetValidator - makes cross chain call to update the Sequencer Uptime Feed on L2
*/
contract StarkNetValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController {
int256 private constant ANSWER_SEQ_OFFLINE = 1;
// Selector hardcoded because StarkNet hash function is not available in this environment
uint256 constant STARK_SELECTOR_UPDATE_STATUS =
1585322027166395525705364165097050997465692350398750944680096081848180365267;
int256 private constant ANSWER_SEQ_OFFLINE = 1;
// Selector hardcoded because StarkNet hash function is not available in this environment
uint256 constant STARK_SELECTOR_UPDATE_STATUS =
1585322027166395525705364165097050997465692350398750944680096081848180365267;

IStarknetMessaging public immutable STARKNET_CROSS_DOMAIN_MESSENGER;
uint256 public immutable L2_UPTIME_FEED_ADDR;
IStarknetMessaging public immutable STARKNET_CROSS_DOMAIN_MESSENGER;
uint256 public immutable L2_UPTIME_FEED_ADDR;

/// @notice StarkNet messaging contract address - the address is 0.
error InvalidStarkNetMessaging();
/// @notice StarkNet messaging contract address - the address is 0.
error InvalidStarkNetMessaging();

/// @notice StarkNet uptime feed address - the address is 0.
error InvalidUptimeFeedAddress();
/// @notice StarkNet uptime feed address - the address is 0.
error InvalidUptimeFeedAddress();

/**
* @param starkNetMessaging the address of the StarkNet Messaging contract address
* @param l2UptimeFeedAddr the address of the Sequencer Uptime Feed on L2
*/
constructor(address starkNetMessaging, uint256 l2UptimeFeedAddr) {
if (starkNetMessaging == address(0)) {
revert InvalidStarkNetMessaging();
}

if (l2UptimeFeedAddr == 0) {
revert InvalidUptimeFeedAddress();
}

STARKNET_CROSS_DOMAIN_MESSENGER = IStarknetMessaging(starkNetMessaging);
L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr;
/**
* @param starkNetMessaging the address of the StarkNet Messaging contract address
* @param l2UptimeFeedAddr the address of the Sequencer Uptime Feed on L2
*/
constructor(address starkNetMessaging, uint256 l2UptimeFeedAddr) {
if (starkNetMessaging == address(0)) {
revert InvalidStarkNetMessaging();
}

/// @notice converts a bool to uint256.
function toUInt256(bool x) internal pure returns (uint256 r) {
assembly {
r := x
}
if (l2UptimeFeedAddr == 0) {
revert InvalidUptimeFeedAddress();
}

/**
* @notice versions:
*
* - StarkNetValidator 0.1.0: initial release
* @inheritdoc TypeAndVersionInterface
*/
function typeAndVersion() external pure virtual override returns (string memory) {
return 'StarkNetValidator 0.1.0';
STARKNET_CROSS_DOMAIN_MESSENGER = IStarknetMessaging(starkNetMessaging);
L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr;
}

/// @notice converts a bool to uint256.
function toUInt256(bool x) internal pure returns (uint256 r) {
assembly {
r := x
}
}

/**
* @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2.
* @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled.
* @param previousAnswer previous aggregator answer
* @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline.
*/
function validate(
uint256, /* previousRoundId */
int256 previousAnswer,
uint256, /* currentRoundId */
int256 currentAnswer
) external override checkAccess returns (bool) {
bool status = currentAnswer == ANSWER_SEQ_OFFLINE;
uint256[] memory payload = new uint256[](2);
/**
* @notice versions:
*
* - StarkNetValidator 0.1.0: initial release
* @inheritdoc TypeAndVersionInterface
*/
function typeAndVersion() external pure virtual override returns (string memory) {
return "StarkNetValidator 0.1.0";
}

// Fill payload with `status` and `timestamp`
payload[0] = toUInt256(status);
payload[1] = block.timestamp;
// Make the StarkNet x-domain call.
// NOTICE: we ignore the output of this call (msgHash, nonce), and we don't raise any events as the event LogMessageToL2 will be emitted from the messaging contract
STARKNET_CROSS_DOMAIN_MESSENGER.sendMessageToL2(L2_UPTIME_FEED_ADDR, STARK_SELECTOR_UPDATE_STATUS, payload);
return true;
}
/**
* @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2.
* @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled.
* @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline.
*/
function validate(
uint256, /* previousRoundId */
int256, /* previousAnswer */
uint256, /* currentRoundId */
int256 currentAnswer
) external override checkAccess returns (bool) {
bool status = currentAnswer == ANSWER_SEQ_OFFLINE;
uint256[] memory payload = new uint256[](2);

// Fill payload with `status` and `timestamp`
payload[0] = toUInt256(status);
payload[1] = block.timestamp;
// Make the StarkNet x-domain call.
// NOTICE: we ignore the output of this call (msgHash, nonce), and we don't raise any events as the event LogMessageToL2 will be emitted from the messaging contract
STARKNET_CROSS_DOMAIN_MESSENGER.sendMessageToL2(L2_UPTIME_FEED_ADDR, STARK_SELECTOR_UPDATE_STATUS, payload);
return true;
}
}
3 changes: 2 additions & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "index.js",
"scripts": {
"compile:cairo": "hardhat starknet-compile",
"compile": "hardhat compile",
"compile:solidity": "hardhat compile",
"compile": "yarn compile:cairo && yarn compile:solidity",
"test": "hardhat --network localhost test"
},
"author": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { number } from 'starknet'
import { StarknetContractFactory, StarknetContract, HttpNetworkConfig } from 'hardhat/types'
import { expect } from 'chai'
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { expectAddressEquality } from './utils'
import { expectAddressEquality } from '../utils'
import { getSelectorFromName } from 'starknet/dist/utils/hash'

describe('StarkNetValidator', () => {
Expand Down Expand Up @@ -33,12 +33,18 @@ describe('StarkNetValidator', () => {
eoaValidator = accounts[1]

const starknetValidatorFactory = await ethers.getContractFactory('StarkNetValidator', deployer)
mockStarkNetMessengerFactory = await ethers.getContractFactory('MockStarkNetMessaging', deployer)
mockStarkNetMessengerFactory = await ethers.getContractFactory(
'MockStarkNetMessaging',
deployer,
)

mockStarkNetMessenger = await mockStarkNetMessengerFactory.deploy()
await mockStarkNetMessenger.deployed()

starkNetValidator = await starknetValidatorFactory.deploy(mockStarkNetMessenger.address, l2Contract.address)
starkNetValidator = await starknetValidatorFactory.deploy(
mockStarkNetMessenger.address,
l2Contract.address,
)

await account.invoke(l2Contract, 'set_l1_sender', { address: starkNetValidator.address })
})
Expand All @@ -52,13 +58,18 @@ describe('StarkNetValidator', () => {
})

it('reverts if called by account with no access', async () => {
await expect(starkNetValidator.connect(eoaValidator).validate(0, 0, 1, 1)).to.be.revertedWith('No access')
await expect(starkNetValidator.connect(eoaValidator).validate(0, 0, 1, 1)).to.be.revertedWith(
'No access',
)
})

it('should deploy the messaging contract', async () => {
starkNetValidator.addAccess(eoaValidator.address)

const { address: deployedTo, l1_provider: L1Provider } = await starknet.devnet.loadL1MessagingContract(networkUrl)
const {
address: deployedTo,
l1_provider: L1Provider,
} = await starknet.devnet.loadL1MessagingContract(networkUrl)

expect(deployedTo).not.to.be.undefined
expect(L1Provider).to.equal(networkUrl)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { starknet } from 'hardhat'
import { StarknetContract, StarknetContractFactory, Account } from 'hardhat/types/runtime'
import { StarknetContract, Account } from 'hardhat/types/runtime'
import { number } from 'starknet'
import { assertErrorMsg } from '../utils'

Expand Down Expand Up @@ -89,13 +89,19 @@ describe('SequencerUptimeFeed test', function () {
it('check interface', async function () {
{
const res = await proxyContract.call('latest_round_data')
expect(res.round.round_id).to.equal(1n)
expect(res.round.answer).to.equal(0n)
}

{
const res = await proxyContract.call('description')
expect(res.description).to.equal(134626335741441605527772921271890603575702899782138692259993464692975953252n)
expect(res.description).to.equal(
134626335741441605527772921271890603575702899782138692259993464692975953252n,
)
}

{
const res = await proxyContract.call('decimals')
expect(res.decimals).to.equal(0n)
}

// TODO: enable access check and assert correct behaviour
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,15 @@ describe('aggregator.cairo', function () {
for (let oracle of oracles.slice(0, f + 1)) {
let [r, s] = ec.sign(oracle.signer, msg)
console.log(
`privKey ${oracle.signer.getPrivate()} r ${r} s ${s} pubKey ${number.toBN(ec.getStarkKey(oracle.signer))}`,
`privKey ${oracle.signer.getPrivate()} r ${r} s ${s} pubKey ${number.toBN(
ec.getStarkKey(oracle.signer),
)}`,
)
signatures.push({ r, s, public_key: number.toBN(ec.getStarkKey(oracle.signer)) })
signatures.push({
r,
s,
public_key: number.toBN(ec.getStarkKey(oracle.signer)),
})
}
console.log('---')

Expand Down Expand Up @@ -307,7 +313,9 @@ describe('aggregator.cairo', function () {
} catch (err: any) {}

// successful accept
await proposed_oracle.invoke(aggregator, 'accept_payeeship', { transmitter })
await proposed_oracle.invoke(aggregator, 'accept_payeeship', {
transmitter,
})
})

it('payments and withdrawals', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ describe('proxy.cairo', function () {
})

// propose it to the proxy
await owner.invoke(proxy, 'propose_aggregator', { address: new_aggregator.address })
await owner.invoke(proxy, 'propose_aggregator', {
address: new_aggregator.address,
})

// query latest round, it should still point to the old aggregator
round = (await proxy.call('latest_round_data')).round
Expand All @@ -86,7 +88,9 @@ describe('proxy.cairo', function () {
assert.equal(round.answer, '12')

// confirm the new aggregator
await owner.invoke(proxy, 'confirm_aggregator', { address: new_aggregator.address })
await owner.invoke(proxy, 'confirm_aggregator', {
address: new_aggregator.address,
})

// query latest round, it should now point to the new aggregator
round = (await proxy.call('latest_round_data')).round
Expand Down
20 changes: 0 additions & 20 deletions contracts/test/starkNetValidator/utils.ts

This file was deleted.

19 changes: 19 additions & 0 deletions contracts/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,22 @@ export const assertErrorMsg = (full: string, expected: string) => {
}
expect.fail('No expected error found: ' + expected)
}

/**
* Receives a hex address, converts it to bigint, converts it back to hex.
* This is done to strip leading zeros.
* @param address a hex string representation of an address
* @returns an adapted hex string representation of the address
*/
function adaptAddress(address: string) {
return '0x' + BigInt(address).toString(16)
}

/**
* Expects address equality after adapting them.
* @param actual
* @param expected
*/
export function expectAddressEquality(actual: string, expected: string) {
expect(adaptAddress(actual)).to.equal(adaptAddress(expected))
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ func readDecimals{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_
let (address) = ocr_address_.read()
let (decimals) = IAggregator.decimals(contract_address=address)
return (decimals)
end
end
Loading

0 comments on commit e7727e3

Please sign in to comment.