From 190a532377a8ea11c507eccefa3e94d88a99c486 Mon Sep 17 00:00:00 2001 From: bayge Date: Wed, 11 Sep 2024 14:52:15 +0930 Subject: [PATCH] Validate parts of the deployment story --- Cargo.toml | 2 +- Makefile | 2 +- deploy-erc20-impl.sh | 2 +- deploy-stylus.sh | 9 ++ deploy.sh | 10 +- docs/src/src/IEvents.sol/interface.IEvents.md | 2 +- .../interface.INineLivesTrading.md | 57 +++++++++++- docs/src/src/Share.sol/contract.Share.md | 2 +- scripts/DeployFactoryTransparentProxy.s.sol | 12 +++ scripts/get-deployment-addresses.sh | 12 +++ src/IEvents.sol | 2 + src/INineLivesTrading.sol | 28 ++++++ src/Share.sol | 16 +++- src/erc20_cd.rs | 30 ++++-- src/factory.rs | 9 +- src/immutables.rs | 13 ++- src/proxy.rs | 91 ++++++++++++++++--- src/trading.rs | 19 +++- test/TestCreate2Trading.sol | 53 +++++++++++ test/TestShare.sol | 32 +++++++ 20 files changed, 358 insertions(+), 45 deletions(-) create mode 100644 deploy-stylus.sh create mode 100644 scripts/DeployFactoryTransparentProxy.s.sol create mode 100755 scripts/get-deployment-addresses.sh create mode 100644 test/TestCreate2Trading.sol create mode 100644 test/TestShare.sol diff --git a/Cargo.toml b/Cargo.toml index 41df9a0c..42a0f39c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,8 @@ array-concat = "0.5.3" sha3-const = "0.1.1" [dev-dependencies] -const-hex = { version = "1.12.0", features = ["alloc"] } proptest = "1.5.0" +const-hex = { version = "1.12.0", features = ["alloc"] } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] alloy-primitives = { version = "0.7.6", features = ["getrandom"] } diff --git a/Makefile b/Makefile index f0c47a54..4414c797 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CARGO_BUILD_STYLUS := \ --artifact-dir . \ --features -.PHONY: build clean +.PHONY: build clean docs OUT_SHARE := out/Share.sol/Share.json diff --git a/deploy-erc20-impl.sh b/deploy-erc20-impl.sh index 3f1113be..9d392f2c 100755 --- a/deploy-erc20-impl.sh +++ b/deploy-erc20-impl.sh @@ -3,6 +3,6 @@ forge create Share \ --json \ --rpc-url="$SPN_SUPERPOSITION_URL" \ - --private-key="$SPN_SUPERPOSITION_KEY" \ + --private-key="$SPN_DEPLOYER_KEY" \ $@ \ | jq -r .deployedTo diff --git a/deploy-stylus.sh b/deploy-stylus.sh new file mode 100644 index 00000000..14004440 --- /dev/null +++ b/deploy-stylus.sh @@ -0,0 +1,9 @@ +#!/bin/sh -eu + +wasm_file="$1" + +cargo stylus deploy \ + --endpoint $SPN_SUPERPOSITION_URL \ + --wasm-file "$wasm_file" \ + --private-key $SPN_SUPERPOSITION_KEY \ + | sed -nr 's/.*deployed code at address: +.*(0x.{40}).*$/\1/p' diff --git a/deploy.sh b/deploy.sh index 2a625b0a..9571d75d 100755 --- a/deploy.sh +++ b/deploy.sh @@ -9,12 +9,16 @@ err() { exit 1 } +[ -z "$SPN_TRADING_IMPL" ] && err "SPN_TRADING_IMPL not set" +[ -z "$SPN_FACTORY_IMPL" ] && err "SPN_FACTORY_IMPL not set" + +# To get these implementation addresses known beforehand (and they +# should be compiled into the contract), you should estimate nonces. + # Deploy the ERC20 implementation... export SPN_ERC20_IMPL="${SPN_ERC20_IMPL:-$(./deploy-erc20-impl.sh)}" echo "export SPN_ERC20_IMPL=$SPN_ERC20_IMPL" >&2 -# Deploy the Trading implemenation... - -# Deploy the factory +forge script --broadcast --json scripts/DeployFactoryTransparentProxy.s.sol diff --git a/docs/src/src/IEvents.sol/interface.IEvents.md b/docs/src/src/IEvents.sol/interface.IEvents.md index c6850ec1..7c0c19be 100644 --- a/docs/src/src/IEvents.sol/interface.IEvents.md +++ b/docs/src/src/IEvents.sol/interface.IEvents.md @@ -1,5 +1,5 @@ # IEvents -[Git Source](https://github.com/fluidity-money/9lives.so/blob/a70b8a6a3d94c40f265a10336f5593b66550e4ec/src/IEvents.sol) +[Git Source](https://github.com/fluidity-money/9lives.so/blob/a3e3525c308d1ecd85b41202701e1c53b0057200/src/IEvents.sol) ## Events diff --git a/docs/src/src/INineLivesTrading.sol/interface.INineLivesTrading.md b/docs/src/src/INineLivesTrading.sol/interface.INineLivesTrading.md index f9b20736..9cbc05ad 100644 --- a/docs/src/src/INineLivesTrading.sol/interface.INineLivesTrading.md +++ b/docs/src/src/INineLivesTrading.sol/interface.INineLivesTrading.md @@ -1,5 +1,5 @@ # INineLivesTrading -[Git Source](https://github.com/fluidity-money/9lives.so/blob/a70b8a6a3d94c40f265a10336f5593b66550e4ec/src/INineLivesTrading.sol) +[Git Source](https://github.com/fluidity-money/9lives.so/blob/a3e3525c308d1ecd85b41202701e1c53b0057200/src/INineLivesTrading.sol) ## Functions @@ -43,3 +43,58 @@ function mintPermit(bytes8 outcome, uint256 value, uint256 deadline, address rec |`s`|`bytes32`|to use for permit.| +### decide + +decide an outcome. Only callable by the oracle! + + +```solidity +function decide(bytes8 outcome) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`outcome`|`bytes8`|to set as the winner.| + + +### payoff + +collect the payoff if holding winning shares! + + +```solidity +function payoff(bytes8 outcomeId, address recipient) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`outcomeId`|`bytes8`|to collect the payoff for.| +|`recipient`|`address`|to send the winnings to.| + + +### details + +details that're available for this outcome. + + +```solidity +function details(bytes8 outcomeId) external view returns (uint256 shares, uint256 invested, bool isWinner); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`outcomeId`|`bytes8`|to get the details for| + + +### invested + +invested amount of fusdc in the betting pool + + +```solidity +function invested() external view returns (uint256); +``` + diff --git a/docs/src/src/Share.sol/contract.Share.md b/docs/src/src/Share.sol/contract.Share.md index ee0ba489..e49af1d9 100644 --- a/docs/src/src/Share.sol/contract.Share.md +++ b/docs/src/src/Share.sol/contract.Share.md @@ -1,5 +1,5 @@ # Share -[Git Source](https://github.com/fluidity-money/9lives.so/blob/a70b8a6a3d94c40f265a10336f5593b66550e4ec/src/Share.sol) +[Git Source](https://github.com/fluidity-money/9lives.so/blob/a3e3525c308d1ecd85b41202701e1c53b0057200/src/Share.sol) **Inherits:** Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable diff --git a/scripts/DeployFactoryTransparentProxy.s.sol b/scripts/DeployFactoryTransparentProxy.s.sol new file mode 100644 index 00000000..9aa32536 --- /dev/null +++ b/scripts/DeployFactoryTransparentProxy.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import {Script, console} from "forge-std/Script.sol"; + +//import "@openzeppelin/contracts/token/ERC20/ERC20Upgradeable.sol"; + +contract DeployFactoryTransparentProxy is Script { + function run() public { + console.log("hello"); + } +} diff --git a/scripts/get-deployment-addresses.sh b/scripts/get-deployment-addresses.sh new file mode 100755 index 00000000..60fb4f47 --- /dev/null +++ b/scripts/get-deployment-addresses.sh @@ -0,0 +1,12 @@ +#!/bin/sh -eu + +get_nonce() { + curl \ + -H 'Content-Type: application/json' \ + -sd "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getTransactionCount\",\"params\":[\"$SPN_DEPLOYER_ADDR\", \"latest\"]}" "$SPN_SUPERPOSITION_URL" \ + | jq -r .result +} + +cur_nonce="$(printf "%d\n" $(get_nonce))" + +echo $((cur_nonce+1)) \ No newline at end of file diff --git a/src/IEvents.sol b/src/IEvents.sol index 06c49937..52c96790 100644 --- a/src/IEvents.sol +++ b/src/IEvents.sol @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; interface IEvents { event NewTrading( diff --git a/src/INineLivesTrading.sol b/src/INineLivesTrading.sol index fda96b4e..48c6b456 100644 --- a/src/INineLivesTrading.sol +++ b/src/INineLivesTrading.sol @@ -29,4 +29,32 @@ interface INineLivesTrading { bytes32 r, bytes32 s ) external returns (uint256); + + /** + * @notice decide an outcome. Only callable by the oracle! + * @param outcome to set as the winner. + */ + function decide(bytes8 outcome) external; + + /** + * @notice collect the payoff if holding winning shares! + * @param outcomeId to collect the payoff for. + * @param recipient to send the winnings to. + */ + function payoff(bytes8 outcomeId, address recipient) external returns (uint256); + + /** + * @notice details that're available for this outcome. + * @param outcomeId to get the details for + */ + function details(bytes8 outcomeId) external view returns ( + uint256 shares, + uint256 invested, + bool isWinner + ); + + /** + * @notice invested amount of fusdc in the betting pool + */ + function invested() external view returns (uint256); } diff --git a/src/Share.sol b/src/Share.sol index 02779ae9..adbff32a 100644 --- a/src/Share.sol +++ b/src/Share.sol @@ -6,6 +6,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; contract Share is Initializable, @@ -13,15 +14,22 @@ contract Share is OwnableUpgradeable, ERC20PermitUpgradeable { - /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function ctor(bytes8 identifier, address admin) initializer public { - __ERC20_init("Shares", ""); + string memory name = string.concat( + "9lives Share #", + Strings.toString(uint256(uint64(identifier))) + ); + string memory symbol = string.concat( + "9#", + Strings.toString(uint256(uint64(identifier))) + ); + __ERC20_init(name, symbol); __Ownable_init(admin); - __ERC20Permit_init("Shares"); + __ERC20Permit_init(name); } function mint(address to, uint256 amount) public onlyOwner { @@ -31,4 +39,4 @@ contract Share is function burn(address owner, uint256 value) public onlyOwner { _burn(owner, value); } -} \ No newline at end of file +} diff --git a/src/erc20_cd.rs b/src/erc20_cd.rs index a05e31cf..f04ea8b8 100644 --- a/src/erc20_cd.rs +++ b/src/erc20_cd.rs @@ -65,13 +65,15 @@ fn test_transfer() { use const_hex; + let b = const_hex::encode(&pack_transfer( + address!("6221a9c005f6e47eb398fd867784cacfdcfff4e7"), + U256::from(123), + )); + assert_eq!( - &pack_transfer( - address!("6221a9c005f6e47eb398fd867784cacfdcfff4e7"), - U256::from(123) - ), - //cast calldata 'transfer(address,uint256)' `{bayge} 123 - "a9059cbb0000000000000000000000006221a9c005f6e47eb398fd867784cacfdcfff4e7000000000000000000000000000000000000000000000000000000000000007b" + b, + //cast calldata 'transfer(address,uint256)' `{bayge} 123 + "a9059cbb0000000000000000000000006221a9c005f6e47eb398fd867784cacfdcfff4e7000000000000000000000000000000000000000000000000000000000000007b" ); } @@ -109,10 +111,22 @@ fn test_pack_permit() { let b = const_hex::encode(&pack_permit( address!("6221a9c005f6e47eb398fd867784cacfdcfff4e7"), address!("feb6034fc7df27df18a3a6bad5fb94c0d3dcb6d5"), - U256::from(100), + U256::from(123), + U256::from(456), + 9, + FixedBytes::from_slice(&[ + 0x1c, 0x8a, 0xff, 0x95, 0x06, 0x85, 0xc2, 0xed, 0x4b, 0xc3, 0x17, 0x4f, 0x34, 0x72, + 0x28, 0x7b, 0x56, 0xd9, 0x51, 0x7b, 0x9c, 0x94, 0x81, 0x27, 0x31, 0x9a, 0x09, 0xa7, + 0xa3, 0x6d, 0xea, 0xc8, + ]), + FixedBytes::from_slice(&[ + 0x84, 0x52, 0xc9, 0xb9, 0x14, 0x02, 0x22, 0xb0, 0x85, 0x93, 0xa2, 0x6d, 0xaa, 0x78, + 0x27, 0x07, 0x29, 0x7b, 0xe9, 0xf7, 0xb3, 0xe8, 0x28, 0x1d, 0x7b, 0x49, 0x74, 0x76, + 0x9f, 0x19, 0xaf, 0xd0, + ]), )); assert_eq!( b, - "0xd505accf0000000000000000000000006221a9c005f6e47eb398fd867784cacfdcfff4e7000000000000000000000000feb6034fc7df27df18a3a6bad5fb94c0d3dcb6d5000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000000091c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac88452c9b9140222b08593a26daa782707297be9f7b3e8281d7b4974769f19afd0" + "d505accf0000000000000000000000006221a9c005f6e47eb398fd867784cacfdcfff4e7000000000000000000000000feb6034fc7df27df18a3a6bad5fb94c0d3dcb6d5000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000000091c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac88452c9b9140222b08593a26daa782707297be9f7b3e8281d7b4974769f19afd0" ); } diff --git a/src/factory.rs b/src/factory.rs index da6f3c52..62045820 100644 --- a/src/factory.rs +++ b/src/factory.rs @@ -3,10 +3,9 @@ use stylus_sdk::{ alloy_primitives::{aliases::*, *}, - msg, + contract, msg, prelude::*, storage::*, - contract }; use crate::{error::*, immutables::*, longtail_call, proxy, share_call, trading_call}; @@ -101,7 +100,11 @@ impl Factory { ); // Start to derive the outcomes that were given to find the share addresses. for outcome_id in outcomes { - longtail_call::pause_pool(proxy::get_share_addr(contract::address(), outcome_id))?; + longtail_call::pause_pool(proxy::get_share_addr( + contract::address(), + msg::sender(), + outcome_id, + ))?; } Ok(()) } diff --git a/src/immutables.rs b/src/immutables.rs index cd58c88c..ea8fb1e3 100644 --- a/src/immutables.rs +++ b/src/immutables.rs @@ -67,11 +67,16 @@ pub const LONGTAIL_TICK_SPACING: u8 = 10; pub const LONGTAIL_MAX_LIQ_PER_TICK: u128 = u128::MAX; +#[test] +#[ignore] +fn print_deployment_bytecode() { + use const_hex::encode; + dbg!(encode(PROXY_BYTECODE), encode(erc20_proxy_code()), encode(trading_proxy_code())); +} + #[test] #[ignore] fn print_proxy_hashes() { - dbg!( - const_hex::encode(erc20_proxy_hash()), - const_hex::encode(trading_proxy_hash()) - ); + use const_hex::encode; + dbg!(encode(erc20_proxy_hash()), encode(trading_proxy_hash())); } diff --git a/src/proxy.rs b/src/proxy.rs index 295a4e61..8e2b6a1c 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -4,40 +4,103 @@ use stylus_sdk::{ deploy::RawDeploy, }; -use crate::immutables::{erc20_proxy_code, trading_proxy_code, erc20_proxy_hash, FACTORY_ADDR}; +use crate::{ + immutables::{erc20_proxy_code, erc20_proxy_hash, trading_proxy_code, trading_proxy_hash}, + proxy, +}; // Sort and concatenate the seeds given, ABI format them, then hash them, // using an offline keccak256 calculation with the native operation. -pub fn create_identifier(seeds: &[&[u8]]) -> FixedBytes<32> { +pub fn create_identifier(seeds: &[&[u8]]) -> FixedBytes<8> { // Sort the seeds in a new vector. let mut seeds = Vec::from(seeds); seeds.sort(); - crypto::keccak(seeds.concat()) + FixedBytes::<8>::from_slice(&crypto::keccak(seeds.concat())[..8]) } // Deploy a new ERC20 using CREATE2 and the seed given. Returns the // address. -pub fn deploy_erc20(seed: FixedBytes<32>) -> Result> { - let d = RawDeploy::new().salt(seed); +pub fn deploy_erc20(seed: FixedBytes<8>) -> Result> { + let d = RawDeploy::new().salt(pad_seed(seed)); let c = erc20_proxy_code(); unsafe { d.deploy(&c, U256::ZERO) } } // Deploy a new Trading contract using CREATE2 and the seed given. Returns the // address. -pub fn deploy_trading(seed: FixedBytes<32>) -> Result> { - let d = RawDeploy::new().salt(seed); +pub fn deploy_trading(seed: FixedBytes<8>) -> Result> { + let d = RawDeploy::new().salt(pad_seed(seed)); let c = trading_proxy_code(); unsafe { d.deploy(&c, U256::ZERO) } } +pub fn get_trading_addr(factory_addr: Address, outcome_ids: &[FixedBytes<8>]) -> Address { + let trading_id = + proxy::create_identifier(&outcome_ids.iter().map(|c| c.as_slice()).collect::>()); + let mut b = [0_u8; 85]; + b[0] = 0xff; + b[1..21].copy_from_slice(factory_addr.as_slice()); + // Leaving some spacing so that we can have an empty part of the word. + b[21..29].copy_from_slice(&trading_id.as_slice()); + b[53..85].copy_from_slice(&trading_proxy_hash()); + Address::from_slice(&crypto::keccak(&b).as_slice()[12..]) +} + +fn pad_seed(seed: FixedBytes<8>) -> FixedBytes<32> { + let mut b = [0_u8; 32]; + b[12..].copy_from_slice(seed.as_slice()); + FixedBytes::from_slice(&b) +} + // Get the share address, using the address of the deployed Trading // contract, and the id associated with the winning outcome. -pub fn get_share_addr(our_addr: Address, outcome_id: FixedBytes<8>) -> Address { - let erc20_id = create_identifier(&[our_addr.as_slice(), outcome_id.as_slice()]); - let mut b = [0xff_u8; 64]; - b[1..20].copy_from_slice(FACTORY_ADDR.as_slice()); - b[20..32].copy_from_slice(erc20_id.as_slice()); - b[32..64].copy_from_slice(&erc20_proxy_hash()); - Address::from_slice(&b) +pub fn get_share_addr( + factory_addr: Address, + trading_addr: Address, + outcome_id: FixedBytes<8>, +) -> Address { + let erc20_id = create_identifier(&[trading_addr.as_slice(), outcome_id.as_slice()]); + let mut b = [0_u8; 85]; + b[0] = 0xff; + b[1..21].copy_from_slice(factory_addr.as_slice()); + // Leaving some spacing so that we can have an empty part of the word. + b[21..29].copy_from_slice(&erc20_id.as_slice()); + b[53..85].copy_from_slice(&erc20_proxy_hash()); + Address::from_slice(&crypto::keccak(&b).as_slice()[12..]) +} + +#[test] +fn test_create_identifier() { + assert_eq!( + create_identifier(&[ + &[0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34], + &[0x22, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34], + ]), + FixedBytes::from_slice(&[ + 0x5e, 0x06, 0xb4, 0x24, 0x49, 0xd1, 0xec, 0xd7, 0x8e, 0x60, 0x3f, 0x85, 0x90, 0x6c, + 0xbe, 0x06, 0x1d, 0xf6, 0xd4, 0x9a, 0xf1, 0x0c, 0xa2, 0x77, 0xef, 0xff, 0x7d, 0xcf, + 0xa6, 0x2e, 0xb7, 0x12, + ]) + ) +} + +#[test] +fn test_get_trading_addr() { + use stylus_sdk::alloy_primitives::address; + let factory = address!("7FA9385bE102ac3EAc297483Dd6233D62b3e1496"); + let outcomes = [ + [0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34], + [0x22, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34], + ] + .map(FixedBytes::<8>::from); + assert_eq!( + const_hex::encode(proxy::create_identifier( + &outcomes.iter().map(|c| c.as_slice()).collect::>() + )), + "5e06b42449d1ecd7" + ); + assert_eq!( + get_trading_addr(factory, &outcomes), + address!("B53687E61d92FC5F11f9231182A9c2ec3a79a739") + ) } diff --git a/src/trading.rs b/src/trading.rs index 6dcadd6b..f9cd9e5a 100644 --- a/src/trading.rs +++ b/src/trading.rs @@ -44,7 +44,7 @@ pub struct Trading { outcome_list: StorageVec>, // Has the outcome here been determined using the determine function? - decided: StorageBool + decided: StorageBool, } #[solidity_storage] @@ -145,7 +145,7 @@ impl Trading { // Get the address of the share, then mint some in line with the // shares we made to the user's address! - let share_addr = proxy::get_share_addr(contract::address(), outcome_id); + let share_addr = proxy::get_share_addr(FACTORY_ADDR, contract::address(), outcome_id); let shares = float::float_to_u256(shares, SHARE_DECIMALS)?; @@ -198,7 +198,7 @@ impl Trading { let outcome = self.outcomes.getter(outcome_id); assert_or!(outcome.winner.get(), Error::NotWinner); // Get the user's balance of the share they own for this outcome. - let share_addr = proxy::get_share_addr(contract::address(), outcome_id); + let share_addr = proxy::get_share_addr(FACTORY_ADDR, contract::address(), outcome_id); // Start to burn their share of the supply to convert to a payoff amount. let share_bal = share_call::balance_of(share_addr, msg::sender())?; share_call::burn(share_addr, msg::sender(), share_bal)?; @@ -211,6 +211,19 @@ impl Trading { fusdc_call::transfer(recipient, fusdc)?; Ok(fusdc) } + + pub fn details(&self, outcome_id: FixedBytes<8>) -> Result<(U256, U256, bool), Error> { + let outcome = self.outcomes.getter(outcome_id); + Ok(( + float::float_to_u256(outcome.shares.get(), SHARE_DECIMALS)?, + float::float_to_u256(outcome.invested.get(), FUSDC_DECIMALS)?, + outcome.winner.get(), + )) + } + + pub fn invested(&self) -> Result { + float::float_to_u256(self.invested.get(), FUSDC_DECIMALS) + } } #[cfg(all(feature = "testing", not(target_arch = "wasm32")))] diff --git a/test/TestCreate2Trading.sol b/test/TestCreate2Trading.sol new file mode 100644 index 00000000..95c18d48 --- /dev/null +++ b/test/TestCreate2Trading.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +// Simple testing code to validate that our CREATE2 approach for creating +// Trading contracts and the offline derivation after. + +contract TestCreate2Trading is Test { + bytes TRADING_CREATE_BYTECODE = hex"60208038033d393d517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55603e8060343d393df3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e610039573d6000fd5b3d6000f30000000000000000000000000000000000000000"; + bytes8 OUTCOME_1 = 0x1234123412341234; + bytes8 OUTCOME_2 = 0x2234123412341234; + function testCreate2Create() public { + bytes memory tradingCreateBytecode = TRADING_CREATE_BYTECODE; + bytes8 outcome1 = OUTCOME_1; + bytes8 outcome2 = OUTCOME_2; + console.log(address(this)); + bytes8 outcome_id = bytes8(keccak256(abi.encodePacked(outcome1, outcome2))); + bytes32 salt = bytes32(outcome_id); + console.logBytes32(salt); + console.logBytes32(keccak256(tradingCreateBytecode)); + address addr; + assembly { + addr := create2( + 0, + add(tradingCreateBytecode, 32), + mload(tradingCreateBytecode), + salt + ) + } + console.log(addr); + } + + function testCreate2Verify() public view { + console.log(address(this)); + bytes8 outcome_id = bytes8(keccak256(abi.encodePacked(OUTCOME_1, OUTCOME_2))); + console.logBytes8(outcome_id); + bytes32 salt = bytes32(outcome_id); + console.logBytes(abi.encodePacked( + hex"ff", + address(this), + salt, + keccak256(TRADING_CREATE_BYTECODE) + )); + console.log(address(uint160(uint(keccak256(abi.encodePacked( + hex"ff", + address(this), + salt, + keccak256(TRADING_CREATE_BYTECODE) + )))))); + } +} diff --git a/test/TestShare.sol b/test/TestShare.sol new file mode 100644 index 00000000..e7fb8aad --- /dev/null +++ b/test/TestShare.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import "../src/Share.sol"; + +contract TestShare is Test { + bytes PROXY_BYTECODE = hex"60208038033d393d517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55603e8060343d393df3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e610039573d6000fd5b3d6000f3"; + + Share share; + + function setUp() public { + address shareImpl = address(new Share()); + bytes memory proxyBytecode = abi.encodePacked(PROXY_BYTECODE, shareImpl); + address share_; + assembly { + share_ := create(0, add(proxyBytecode, 32), mload(proxyBytecode)) + } + share = Share(share_); + share.ctor(0x1234123412341234, address(this)); + } + + function testSymbol() public view { + assertEq(share.symbol(), "9#1311693406324658740"); + } + + function testName() public view { + assertEq(share.name(), "9lives Share #1311693406324658740"); + } +}