Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement RedStone push oracle contracts #207

Open
wants to merge 10 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.devnet
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ L2_VESTING_WALLET_OWNER_ADDRESS=0x
# Airdrop wallet address where LSK tokens are transferred to after airdrop period ends
L2_AIRDROP_WALLET_ADDRESS=0x

# Owner of L2MultiFeedAdapter* and L2PriceFeed* contracts
L2_ADAPTER_PRICEFEED_OWNER_ADDRESS=0x

# Salt for deterministic smart contract address generation
DETERMINISTIC_ADDRESS_SALT="lisk_l2_token_salt_dev_network"

Expand Down
3 changes: 3 additions & 0 deletions .env.mainnet
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ L2_AIRDROP_OWNER_ADDRESS=0x394Ae9d48eeca1C69a989B5A8C787081595c55A7
# Airdrop wallet address where LSK tokens are transferred to after airdrop period ends
L2_AIRDROP_WALLET_ADDRESS=0x0c92121A7C15cF01041e1122483Bc173Baccd877

# Owner of L2MultiFeedAdapter* and L2PriceFeed* contracts
L2_ADAPTER_PRICEFEED_OWNER_ADDRESS=0x394Ae9d48eeca1C69a989B5A8C787081595c55A7

# Salt for deterministic smart contract address generation
DETERMINISTIC_ADDRESS_SALT="lisk_l2_token_deterministic_salt"

Expand Down
3 changes: 3 additions & 0 deletions .env.testnet
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ L2_VESTING_WALLET_OWNER_ADDRESS=0x84277C9255b3B6904aCfe12C2c45c6a36E81B059
# Airdrop wallet address where LSK tokens are transferred to after airdrop period ends
L2_AIRDROP_WALLET_ADDRESS=0xaF3f4B5033Ef666b3F3EA91a0f360541cC21e5d7

# Owner of L2MultiFeedAdapter* and L2PriceFeed* contracts
L2_ADAPTER_PRICEFEED_OWNER_ADDRESS=0x84277C9255b3B6904aCfe12C2c45c6a36E81B059

# Salt for deterministic smart contract address generation
DETERMINISTIC_ADDRESS_SALT="lisk_l2_token_salt_test_network"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fail-fast: true
matrix:
system:
- os: macos-12
- os: macos-latest
target: x86_64-apple-darwin
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
[submodule "lib/openzeppelin-foundry-upgrades"]
path = lib/openzeppelin-foundry-upgrades
url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
[submodule "lib/redstone-oracles-monorepo"]
path = lib/redstone-oracles-monorepo
url = https://github.com/redstone-finance/redstone-oracles-monorepo
[submodule "lib/chainlink"]
path = lib/chainlink
url = https://github.com/smartcontractkit/chainlink
6 changes: 6 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ solc_version = "0.8.23"
optimizer = true
optimizer_runs = 200
remappings = [
'@openzeppelin/contracts-upgradeable/proxy/=lib/openzeppelin-contracts-upgradeable/contracts/proxy/',
'@openzeppelin/=lib/openzeppelin-contracts/',
'@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/',
'ds-test/=lib/forge-std/lib/ds-test/src/',
Expand All @@ -19,6 +20,11 @@ remappings = [
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/',
'openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/',
'solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/',
'ERC4626/=lib/properties/lib/ERC4626/contracts/',
'properties/=lib/properties/contracts/',
'@redstone-finance/=lib/redstone-oracles-monorepo/packages/',
'solmate/=lib/properties/lib/solmate/src/',
'@chainlink=lib/chainlink/',
]
deny_warnings = true
ignored_warnings_from = [
Expand Down
1 change: 1 addition & 0 deletions lib/chainlink
Submodule chainlink added at 3cf93c
1 change: 1 addition & 0 deletions lib/redstone-oracles-monorepo
60 changes: 60 additions & 0 deletions script/10_deployMultiFeedAdaptersWithoutRounds.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bash

echo "Instructing the shell to exit immediately if any command returns a non-zero exit status..."
set -e
echo "Done."

echo "Navigating to the root directory of the project..."
cd ../
echo "Done."

echo "Setting environment variables..."
source .env
echo "Done."

echo "Creating $NETWORK directory inside deployment/artifacts/contracts directory..."
if [ -z "$NETWORK" ]
then
echo "NETWORK variable inside .env file is not set. Please set NETWORK environment variable."
exit 1
else
if [ -d "deployment/artifacts/contracts/$NETWORK" ]
then
echo "Directory deployment/artifacts/contracts/$NETWORK already exists."
else
mkdir deployment/artifacts/contracts/$NETWORK
fi
fi
echo "Done."
sameersubudhi marked this conversation as resolved.
Show resolved Hide resolved

echo "Deploying and if enabled verifying L2MultiFeedAdapterWithoutRoundsPrimaryProd smart contract..."
if [ -z "$CONTRACT_VERIFIER" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsPrimaryProd.s.sol:L2MultiFeedAdapterWithoutRoundsPrimaryProdScript
else
if [ $CONTRACT_VERIFIER = "blockscout" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier blockscout --verifier-url $L2_VERIFIER_URL -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsPrimaryProd.s.sol:L2MultiFeedAdapterWithoutRoundsPrimaryProdScript
fi
if [ $CONTRACT_VERIFIER = "etherscan" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier etherscan --etherscan-api-key="$L2_ETHERSCAN_API_KEY" -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsPrimaryProd.s.sol:L2MultiFeedAdapterWithoutRoundsPrimaryProdScript
fi
fi
echo "Done."

echo "Deploying and if enabled verifying L2MultiFeedAdapterWithoutRoundsMainDemo smart contract..."
if [ -z "$CONTRACT_VERIFIER" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsMainDemo.s.sol:L2MultiFeedAdapterWithoutRoundsMainDemoScript
else
if [ $CONTRACT_VERIFIER = "blockscout" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier blockscout --verifier-url $L2_VERIFIER_URL -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsMainDemo.s.sol:L2MultiFeedAdapterWithoutRoundsMainDemoScript
fi
if [ $CONTRACT_VERIFIER = "etherscan" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier etherscan --etherscan-api-key="$L2_ETHERSCAN_API_KEY" -vvvv script/contracts/L2/L2MultiFeedAdapterWithoutRoundsMainDemo.s.sol:L2MultiFeedAdapterWithoutRoundsMainDemoScript
fi
fi
echo "Done."
sameersubudhi marked this conversation as resolved.
Show resolved Hide resolved
76 changes: 76 additions & 0 deletions script/11_deployPriceFeedsWithoutRounds.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash

echo "Instructing the shell to exit immediately if any command returns a non-zero exit status..."
set -e
echo "Done."

echo "Navigating to the root directory of the project..."
cd ../
echo "Done."

echo "Setting environment variables..."
source .env
echo "Done."

echo "Creating $NETWORK directory inside deployment/artifacts/contracts directory..."
if [ -z "$NETWORK" ]
then
echo "NETWORK variable inside .env file is not set. Please set NETWORK environment variable."
exit 1
else
if [ -d "deployment/artifacts/contracts/$NETWORK" ]
then
echo "Directory deployment/artifacts/contracts/$NETWORK already exists."
else
mkdir deployment/artifacts/contracts/$NETWORK
fi
fi
echo "Done."

echo "Deploying and if enabled verifying L2PriceFeedWithoutRoundsFactory smart contract..."
if [ -z "$CONTRACT_VERIFIER" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast -vvvv script/contracts/L2/L2PriceFeedWithoutRoundsFactory.s.sol:L2PriceFeedWithoutRoundsFactoryScript
else
if [ $CONTRACT_VERIFIER = "blockscout" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier blockscout --verifier-url $L2_VERIFIER_URL -vvvv script/contracts/L2/L2PriceFeedWithoutRoundsFactory.s.sol:L2PriceFeedWithoutRoundsFactoryScript
fi
if [ $CONTRACT_VERIFIER = "etherscan" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier etherscan --etherscan-api-key="$L2_ETHERSCAN_API_KEY" -vvvv script/contracts/L2/L2PriceFeedWithoutRoundsFactory.s.sol:L2PriceFeedWithoutRoundsFactoryScript
fi
fi
echo "Done."

echo "Deploying and if enabled verifying L2PriceFeedWithoutRounds smart contract for USDT/USD..."
if [ -z "$CONTRACT_VERIFIER" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "USDT" "PrimaryProd"
else
if [ $CONTRACT_VERIFIER = "blockscout" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier blockscout --verifier-url $L2_VERIFIER_URL -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "USDT" "PrimaryProd"
fi
if [ $CONTRACT_VERIFIER = "etherscan" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier etherscan --etherscan-api-key="$L2_ETHERSCAN_API_KEY" -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "USDT" "PrimaryProd"
fi
fi
echo "Done."

echo "Deploying and if enabled verifying L2PriceFeedWithoutRounds smart contract for LSK/USD..."
if [ -z "$CONTRACT_VERIFIER" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "LSK" "MainDemo"
else
if [ $CONTRACT_VERIFIER = "blockscout" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier blockscout --verifier-url $L2_VERIFIER_URL -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "LSK" "MainDemo"
fi
if [ $CONTRACT_VERIFIER = "etherscan" ]
then
forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --verifier etherscan --etherscan-api-key="$L2_ETHERSCAN_API_KEY" -vvvv --sig "run(string,string)" script/contracts/L2/L2PriceFeedWithoutRounds.s.sol:L2PriceFeedWithoutRoundsScript "LSK" "MainDemo"
fi
fi
echo "Done."
84 changes: 84 additions & 0 deletions script/contracts/L2/L2MultiFeedAdapterWithoutRoundsMainDemo.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.23;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { Script, console2 } from "forge-std/Script.sol";
import { L2MultiFeedAdapterWithoutRoundsMainDemo } from "src/L2/L2MultiFeedAdapterWithoutRoundsMainDemo.sol";
import "script/contracts/Utils.sol";

/// @title L2MultiFeedAdapterWithoutRoundsMainDemoScript - L2MultiFeedAdapterWithoutRoundsMainDemo deployment
/// script
/// @notice This contract is used to deploy L2MultiFeedAdapterWithoutRoundsMainDemo contract.
contract L2MultiFeedAdapterWithoutRoundsMainDemoScript is Script {
/// @notice Utils contract which provides functions to read and write JSON files containing L2 addresses.
Utils utils;

function setUp() public {
utils = new Utils();
}

/// @notice This function deploys L2MultiFeedAdapterWithoutRoundsMainDemo contract.
function run() public {
// Deployer's private key. Owner of the L2MultiFeedAdapterWithoutRoundsMainDemo. PRIVATE_KEY is set in .env
// file.
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

console2.log("Deploying L2MultiFeedAdapterWithoutRoundsMainDemo contract...");

// owner Address, the ownership of L2MultiFeedAdapterWithoutRoundsMainDemo proxy contract is transferred to
// after deployment
address ownerAddress = vm.envAddress("L2_ADAPTER_PRICEFEED_OWNER_ADDRESS");
assert(ownerAddress != address(0));
console2.log(
"L2 MultiFeed Adapter Without Rounds MainDemo contract owner address: %s (after ownership will be accepted)",
ownerAddress
);

// deploy L2MultiFeedAdapterWithoutRoundsMainDemo implementation contract
vm.startBroadcast(deployerPrivateKey);
L2MultiFeedAdapterWithoutRoundsMainDemo l2AdapterImplementation = new L2MultiFeedAdapterWithoutRoundsMainDemo();
vm.stopBroadcast();

assert(address(l2AdapterImplementation) != address(0));

// ERC1967Utils: keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
assert(
l2AdapterImplementation.proxiableUUID() == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)
);

// deploy L2MultiFeedAdapterWithoutRoundsMainDemo proxy contract and at the same time initialize the proxy
// contract (calls the initialize function in L2MultiFeedAdapterWithoutRoundsMainDemo)
vm.startBroadcast(deployerPrivateKey);
ERC1967Proxy l2AdapterProxy = new ERC1967Proxy(
address(l2AdapterImplementation), abi.encodeWithSelector(l2AdapterImplementation.initialize.selector)
);
vm.stopBroadcast();
assert(address(l2AdapterProxy) != address(0));

// wrap in ABI to support easier calls
L2MultiFeedAdapterWithoutRoundsMainDemo l2Adapter =
L2MultiFeedAdapterWithoutRoundsMainDemo(address(l2AdapterProxy));
assert(l2Adapter.getUniqueSignersThreshold() == 1);
assert(l2Adapter.getAuthorisedSignerIndex(0x0C39486f770B26F5527BBBf942726537986Cd7eb) == 0);

// transfer ownership of L2MultiFeedAdapterWithoutRoundsMainDemo proxy; because of using
// Ownable2StepUpgradeable contract, new owner has to accept ownership
vm.startBroadcast(deployerPrivateKey);
l2Adapter.transferOwnership(ownerAddress);
vm.stopBroadcast();
assert(l2Adapter.owner() == vm.addr(deployerPrivateKey)); // ownership is not yet accepted

console2.log("L2 MultiFeed Adapter Without Rounds MainDemo contract successfully deployed!");
console2.log("L2 MultiFeed Adapter (Implementation) address: %s", address(l2AdapterImplementation));
console2.log("L2 MultiFeed Adapter (Proxy) address: %s", address(l2Adapter));
console2.log(
"Owner of L2 MultiFeed Adapter (Proxy) address: %s (after ownership will be accepted)", ownerAddress
);

// write L2MultiFeedAdapterWithoutRoundsMainDemo address to l2addresses.json
Utils.L2AddressesConfig memory l2AddressesConfig = utils.readL2AddressesFile(utils.getL2AddressesFilePath());
l2AddressesConfig.L2MultiFeedAdapterWithoutRoundsMainDemoImplementation = address(l2AdapterImplementation);
l2AddressesConfig.L2MultiFeedAdapterWithoutRoundsMainDemo = address(l2Adapter);
utils.writeL2AddressesFile(l2AddressesConfig, utils.getL2AddressesFilePath());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.23;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { Script, console2 } from "forge-std/Script.sol";
import { L2MultiFeedAdapterWithoutRoundsPrimaryProd } from "src/L2/L2MultiFeedAdapterWithoutRoundsPrimaryProd.sol";
import "script/contracts/Utils.sol";

/// @title L2MultiFeedAdapterWithoutRoundsPrimaryProdScript - L2MultiFeedAdapterWithoutRoundsPrimaryProd deployment
/// script
/// @notice This contract is used to deploy L2MultiFeedAdapterWithoutRoundsPrimaryProd contract.
contract L2MultiFeedAdapterWithoutRoundsPrimaryProdScript is Script {
/// @notice Utils contract which provides functions to read and write JSON files containing L2 addresses.
Utils utils;

function setUp() public {
utils = new Utils();
}

/// @notice This function deploys L2MultiFeedAdapterWithoutRoundsPrimaryProd contract.
function run() public {
// Deployer's private key. Owner of the L2MultiFeedAdapterWithoutRoundsPrimaryProd. PRIVATE_KEY is set in .env
// file.
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

console2.log("Deploying L2MultiFeedAdapterWithoutRoundsPrimaryProd contract...");

// owner Address, the ownership of L2MultiFeedAdapterWithoutRoundsPrimaryProd proxy contract is transferred to
// after deployment
address ownerAddress = vm.envAddress("L2_ADAPTER_PRICEFEED_OWNER_ADDRESS");
assert(ownerAddress != address(0));
console2.log(
"L2 MultiFeed Adapter Without Rounds PrimaryProd contract owner address: %s (after ownership will be accepted)",
ownerAddress
);

// deploy L2MultiFeedAdapterWithoutRoundsPrimaryProd implementation contract
vm.startBroadcast(deployerPrivateKey);
L2MultiFeedAdapterWithoutRoundsPrimaryProd l2AdapterImplementation =
new L2MultiFeedAdapterWithoutRoundsPrimaryProd();
vm.stopBroadcast();

assert(address(l2AdapterImplementation) != address(0));

// ERC1967Utils: keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
assert(
l2AdapterImplementation.proxiableUUID() == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)
);

// deploy L2MultiFeedAdapterWithoutRoundsPrimaryProd proxy contract and at the same time initialize the proxy
// contract (calls the initialize function in L2MultiFeedAdapterWithoutRoundsPrimaryProd)
vm.startBroadcast(deployerPrivateKey);
ERC1967Proxy l2AdapterProxy = new ERC1967Proxy(
address(l2AdapterImplementation), abi.encodeWithSelector(l2AdapterImplementation.initialize.selector)
);
vm.stopBroadcast();
assert(address(l2AdapterProxy) != address(0));

// wrap in ABI to support easier calls
L2MultiFeedAdapterWithoutRoundsPrimaryProd l2Adapter =
L2MultiFeedAdapterWithoutRoundsPrimaryProd(address(l2AdapterProxy));
assert(l2Adapter.getUniqueSignersThreshold() == 2);
assert(l2Adapter.getAuthorisedSignerIndex(0x8BB8F32Df04c8b654987DAaeD53D6B6091e3B774) == 0);
assert(l2Adapter.getAuthorisedSignerIndex(0xdEB22f54738d54976C4c0fe5ce6d408E40d88499) == 1);
assert(l2Adapter.getAuthorisedSignerIndex(0x51Ce04Be4b3E32572C4Ec9135221d0691Ba7d202) == 2);
assert(l2Adapter.getAuthorisedSignerIndex(0xDD682daEC5A90dD295d14DA4b0bec9281017b5bE) == 3);
assert(l2Adapter.getAuthorisedSignerIndex(0x9c5AE89C4Af6aA32cE58588DBaF90d18a855B6de) == 4);

// transfer ownership of L2MultiFeedAdapterWithoutRoundsPrimaryProd proxy; because of using
// Ownable2StepUpgradeable contract, new owner has to accept ownership
vm.startBroadcast(deployerPrivateKey);
l2Adapter.transferOwnership(ownerAddress);
vm.stopBroadcast();
assert(l2Adapter.owner() == vm.addr(deployerPrivateKey)); // ownership is not yet accepted

console2.log("L2 MultiFeed Adapter Without Rounds PrimaryProd contract successfully deployed!");
console2.log("L2 MultiFeed Adapter (Implementation) address: %s", address(l2AdapterImplementation));
console2.log("L2 MultiFeed Adapter (Proxy) address: %s", address(l2Adapter));
console2.log(
"Owner of L2 MultiFeed Adapter (Proxy) address: %s (after ownership will be accepted)", ownerAddress
);

// write L2MultiFeedAdapterWithoutRoundsPrimaryProd address to l2addresses.json
Utils.L2AddressesConfig memory l2AddressesConfig = utils.readL2AddressesFile(utils.getL2AddressesFilePath());
l2AddressesConfig.L2MultiFeedAdapterWithoutRoundsPrimaryProdImplementation = address(l2AdapterImplementation);
l2AddressesConfig.L2MultiFeedAdapterWithoutRoundsPrimaryProd = address(l2Adapter);
utils.writeL2AddressesFile(l2AddressesConfig, utils.getL2AddressesFilePath());
}
}
Loading
Loading