added dev files
This commit is contained in:
parent
ebd2a14cb6
commit
354d6c5fee
|
@ -0,0 +1,7 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
||||
test-ledger
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
node_modules
|
||||
dist
|
||||
build
|
||||
test-ledger
|
|
@ -0,0 +1,14 @@
|
|||
[features]
|
||||
seeds = false
|
||||
[programs.localnet]
|
||||
anchor_contributor = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[registry]
|
||||
url = "https://anchor.projectserum.com"
|
||||
|
||||
[provider]
|
||||
cluster = "localnet"
|
||||
wallet = "./tests/test_keypair.json"
|
||||
|
||||
[scripts]
|
||||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"programs/*"
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
// Migrations are an early feature. Currently, they're nothing more than this
|
||||
// single deploy script that's invoked from the CLI, injecting a provider
|
||||
// configured from the workspace's Anchor.toml.
|
||||
|
||||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
module.exports = async function (provider) {
|
||||
// Configure client to use the provider.
|
||||
anchor.setProvider(provider);
|
||||
|
||||
// Add your deploy script here.
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"scripts": {
|
||||
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
|
||||
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certusone/wormhole-sdk": "^0.3.4",
|
||||
"@project-serum/anchor": "^0.24.2",
|
||||
"ethers": "^5.6.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bn.js": "^5.1.0",
|
||||
"@types/chai": "^4.3.0",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^9.0.3",
|
||||
"prettier": "^2.6.2",
|
||||
"ts-mocha": "^8.0.0",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "anchor-contributor"
|
||||
version = "0.1.0"
|
||||
description = "ICCO Contributor"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "anchor_contributor"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[profile.release]
|
||||
overflow-checks = true
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = "0.24.2"
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.3"
|
||||
borsh = "0.9.3"
|
|
@ -0,0 +1,3 @@
|
|||
pub const CORE_BRIDGE_ADDRESS: &str = "Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o";
|
||||
pub const TOKEN_BRIDGE_ADDRESS: &str = "B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE";
|
||||
pub const SEED_PREFIX_SALE: &str = "icco-sale";
|
|
@ -0,0 +1,55 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use crate::state::*;
|
||||
use crate::constants::*;
|
||||
use std::str::FromStr;
|
||||
use crate::wormhole::*;
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(conductor_chain:u16, conductor_address:Vec<u8>)]
|
||||
pub struct CreateContributor<'info> {
|
||||
#[account(
|
||||
init,
|
||||
payer = owner,
|
||||
space = 8 + Contributor::MAXIMUM_SIZE,
|
||||
seeds = [
|
||||
b"contributor".as_ref(),
|
||||
conductor_address.as_ref()
|
||||
],
|
||||
bump
|
||||
)]
|
||||
pub contributor: Account<'info, Contributor>,
|
||||
|
||||
#[account(mut)]
|
||||
pub owner: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct InitSale<'info> {
|
||||
pub contributor: Account<'info, Contributor>,
|
||||
|
||||
#[account(
|
||||
init,
|
||||
seeds = [
|
||||
SEED_PREFIX_SALE.as_bytes().as_ref(),
|
||||
(PostedMessageData::try_from_slice(&core_bridge_vaa.data.borrow())?.0).sequence.to_be_bytes().as_ref()
|
||||
],
|
||||
payer = owner,
|
||||
bump,
|
||||
space = Sale::MAXIMUM_SIZE
|
||||
)]
|
||||
pub sale: Account<'info, Sale>,
|
||||
|
||||
#[account(
|
||||
constraint = core_bridge_vaa.to_account_info().owner == &Pubkey::from_str(CORE_BRIDGE_ADDRESS).unwrap(),
|
||||
constraint = (PostedMessageData::try_from_slice(&core_bridge_vaa.data.borrow())?.0).emitter_chain == contributor.conductor_chain,
|
||||
constraint = (PostedMessageData::try_from_slice(&core_bridge_vaa.data.borrow())?.0).emitter_address == contributor.conductor_address
|
||||
)]
|
||||
/// CHECK: This account is owned by Core Bridge so we trust it
|
||||
pub core_bridge_vaa: AccountInfo<'info>,
|
||||
|
||||
#[account(mut)]
|
||||
pub owner: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
#[error_code]
|
||||
pub enum ContributorError {
|
||||
#[msg("InvalidConductor")]
|
||||
InvalidConductor,
|
||||
}
|
||||
|
||||
#[error_code]
|
||||
pub enum SaleError {
|
||||
#[msg("IncorrectSale")]
|
||||
IncorrectSale,
|
||||
|
||||
#[msg("IncorrectVaaPayload")]
|
||||
IncorrectVaaPayload,
|
||||
|
||||
#[msg("InvalidVaaAction")]
|
||||
InvalidVaaAction,
|
||||
|
||||
#[msg("SaleEnded")]
|
||||
SaleEnded,
|
||||
|
||||
#[msg("SaleNotFinished")]
|
||||
SaleNotFinished,
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
mod context;
|
||||
mod state;
|
||||
mod wormhole;
|
||||
mod error;
|
||||
mod constants;
|
||||
|
||||
use constants::*;
|
||||
use context::*;
|
||||
use state::*;
|
||||
use error::*;
|
||||
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod anchor_contributor {
|
||||
use super::*;
|
||||
|
||||
pub fn create_contributor(
|
||||
ctx: Context<CreateContributor>,
|
||||
conductor_chain: u16,
|
||||
conductor_address: Vec<u8>,
|
||||
) -> Result<()> {
|
||||
let contributor = &mut ctx.accounts.contributor;
|
||||
|
||||
// there isn't a solana conductor (yet? bwahaha)
|
||||
require!(conductor_chain != 1u16, ContributorError::InvalidConductor);
|
||||
|
||||
contributor.conductor_chain = conductor_chain;
|
||||
contributor.conductor_address =
|
||||
conductor_address.try_into().expect("incorrect byte length");
|
||||
contributor.owner = ctx.accounts.owner.key();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_sale(ctx:Context<InitSale>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Initialize {}
|
|
@ -0,0 +1,60 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use crate::wormhole::*;
|
||||
use num_derive::*;
|
||||
use borsh::{BorshDeserialize};
|
||||
use std::{
|
||||
io::Write,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#[account]
|
||||
#[derive(Default)]
|
||||
pub struct Contributor {
|
||||
pub owner: Pubkey,
|
||||
pub conductor_chain: u16,
|
||||
pub conductor_address: [u8; 32],
|
||||
}
|
||||
|
||||
impl Contributor {
|
||||
pub const MAXIMUM_SIZE: usize = 2 + 32 + 32 + 1;
|
||||
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct Sale {
|
||||
token_address: Vec<u8>, // 32
|
||||
token_chain: u16, // 2
|
||||
token_decimals: u8, // 1
|
||||
times: SaleTimes, // 8 + 8
|
||||
recipient: [u8; 32], // 32
|
||||
num_accepted: u8, // 1
|
||||
status: SaleStatus, // 1
|
||||
|
||||
pub id: Vec<u8>, // 32
|
||||
pub bump: u8, // 1
|
||||
}
|
||||
|
||||
impl Sale {
|
||||
pub const MAXIMUM_SIZE: usize = 32 + 32 + 2 + 1 + 8 + 8 + 32 + 1 + 1 + 1;
|
||||
}
|
||||
|
||||
pub fn parse_sale_payload(payload: Vec<u8>){
|
||||
|
||||
}
|
||||
|
||||
|
||||
#[derive(AnchorSerialize, AnchorDeserialize, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct SaleTimes {
|
||||
start: u64,
|
||||
end: u64,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
AnchorSerialize, AnchorDeserialize, FromPrimitive, ToPrimitive, Copy, Clone, PartialEq, Eq,
|
||||
)]
|
||||
pub enum SaleStatus {
|
||||
Active,
|
||||
Sealed,
|
||||
Aborted,
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use std::{
|
||||
io::Write,
|
||||
};
|
||||
|
||||
#[derive(AnchorDeserialize, AnchorSerialize)]
|
||||
pub struct PostMessageData {
|
||||
/// Unique nonce for this message
|
||||
pub nonce: u32,
|
||||
|
||||
/// Message payload
|
||||
pub payload: Vec<u8>,
|
||||
|
||||
/// Commitment Level required for an attestation to be produced
|
||||
pub consistency_level: ConsistencyLevel,
|
||||
}
|
||||
|
||||
#[derive(AnchorDeserialize, AnchorSerialize)]
|
||||
pub enum ConsistencyLevel {
|
||||
Confirmed,
|
||||
Finalized
|
||||
}
|
||||
|
||||
#[derive(AnchorDeserialize, AnchorSerialize)]
|
||||
pub enum Instruction{
|
||||
Initialize,
|
||||
PostMessage,
|
||||
PostVAA,
|
||||
SetFees,
|
||||
TransferFees,
|
||||
UpgradeContract,
|
||||
UpgradeGuardianSet,
|
||||
VerifySignatures,
|
||||
}
|
||||
|
||||
#[derive(AnchorDeserialize, AnchorSerialize, Clone)]
|
||||
pub struct BridgeData {
|
||||
/// The current guardian set index, used to decide which signature sets to accept.
|
||||
pub guardian_set_index: u32,
|
||||
|
||||
/// Lamports in the collection account
|
||||
pub last_lamports: u64,
|
||||
|
||||
/// Bridge configuration, which is set once upon initialization.
|
||||
pub config: BridgeConfig,
|
||||
}
|
||||
|
||||
#[derive(AnchorDeserialize, AnchorSerialize, Clone)]
|
||||
pub struct BridgeConfig {
|
||||
/// Period for how long a guardian set is valid after it has been replaced by a new one. This
|
||||
/// guarantees that VAAs issued by that set can still be submitted for a certain period. In
|
||||
/// this period we still trust the old guardian set.
|
||||
pub guardian_set_expiration_time: u32,
|
||||
|
||||
/// Amount of lamports that needs to be paid to the protocol to post a message
|
||||
pub fee: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PostedMessageData(pub MessageData);
|
||||
|
||||
#[derive(Debug, Default, BorshDeserialize, BorshSerialize)]
|
||||
pub struct MessageData {
|
||||
/// Header of the posted VAA
|
||||
pub vaa_version: u8,
|
||||
|
||||
/// Level of consistency requested by the emitter
|
||||
pub consistency_level: u8,
|
||||
|
||||
/// Time the vaa was submitted
|
||||
pub vaa_time: u32,
|
||||
|
||||
/// Account where signatures are stored
|
||||
pub vaa_signature_account: Pubkey,
|
||||
|
||||
/// Time the posted message was created
|
||||
pub submission_time: u32,
|
||||
|
||||
/// Unique nonce for this message
|
||||
pub nonce: u32,
|
||||
|
||||
/// Sequence number of this message
|
||||
pub sequence: u64,
|
||||
|
||||
/// Emitter of the message
|
||||
pub emitter_chain: u16,
|
||||
|
||||
/// Emitter of the message
|
||||
pub emitter_address: [u8; 32],
|
||||
|
||||
/// Message payload
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
impl AnchorSerialize for PostedMessageData {
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write(b"msg")?;
|
||||
BorshSerialize::serialize(&self.0, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl AnchorDeserialize for PostedMessageData {
|
||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||
*buf = &buf[3..];
|
||||
Ok(PostedMessageData(
|
||||
<MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import * as anchor from "@project-serum/anchor";
|
||||
import { Program } from "@project-serum/anchor";
|
||||
import { AnchorContributor } from "../target/types/anchor_contributor";
|
||||
import {
|
||||
tryNativeToUint8Array
|
||||
} from '@certusone/wormhole-sdk';
|
||||
import { findProgramAddressSync } from "@project-serum/anchor/dist/cjs/utils/pubkey";
|
||||
import fs from 'fs';
|
||||
|
||||
describe("anchor-contributor", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.AnchorContributor as Program<AnchorContributor>;
|
||||
|
||||
const CONDUCTOR_CHAIN = 2;
|
||||
const CONDUCTOR_ADDRESS = tryNativeToUint8Array('0x5c49f34D92316A2ac68d10A1e2168e16610e84f9', "ethereum");
|
||||
const owner = anchor.web3.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(fs.readFileSync("./tests/test_keypair.json").toString())))
|
||||
const [contributor_acc, contributor_bmp] = findProgramAddressSync([
|
||||
Buffer.from("contributor"),
|
||||
CONDUCTOR_ADDRESS
|
||||
], program.programId)
|
||||
|
||||
it("creates conductor", async () => {
|
||||
await program.methods
|
||||
.createContributor(
|
||||
CONDUCTOR_CHAIN,
|
||||
Buffer.from(CONDUCTOR_ADDRESS)
|
||||
)
|
||||
.accounts({
|
||||
owner: owner.publicKey,
|
||||
contributor: contributor_acc,
|
||||
systemProgram: anchor.web3.SystemProgram.programId
|
||||
})
|
||||
.rpc()
|
||||
|
||||
console.log(await program.account.contributor.fetch(contributor_acc));
|
||||
});
|
||||
|
||||
it("initalizes a sale", async () => {
|
||||
|
||||
})
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
[128,234,237,75,126,9,5,95,22,89,161,204,162,155,126,118,233,0,87,171,69,102,211,233,50,152,163,63,145,5,132,63,158,238,105,62,204,112,139,148,240,143,108,17,236,215,6,163,114,46,101,158,161,227,52,43,109,225,184,233,161,235,186,224]
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": ["mocha", "chai"],
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"lib": ["es2015"],
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,15 @@
|
|||
[features]
|
||||
seeds = false
|
||||
[programs.localnet]
|
||||
icco = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
icco_contributor = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
contributor = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[registry]
|
||||
url = "https://anchor.projectserum.com"
|
||||
|
||||
[provider]
|
||||
cluster = "localnet"
|
||||
wallet = "/Users/spacemandev/.config/solana/id.json"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[scripts]
|
||||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
|
||||
|
|
|
@ -421,6 +421,13 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "contributor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anchor-lang",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.2"
|
||||
|
@ -604,7 +611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "icco-contributor"
|
||||
name = "icco_contributor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anchor-lang",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "contributor"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "contributor"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[profile.release]
|
||||
overflow-checks = true
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = "0.24.2"
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -0,0 +1,15 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod contributor {
|
||||
use super::*;
|
||||
|
||||
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Initialize {}
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "icco-contributor"
|
||||
name = "icco_contributor"
|
||||
version = "0.1.0"
|
||||
description = "ICCO Contributor"
|
||||
edition = "2021"
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -13,6 +13,10 @@ pub mod wormhole;
|
|||
pub mod icco_contributor {
|
||||
use super::*;
|
||||
|
||||
pub fn debug(ctx: Context<Debug>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_contributor(
|
||||
ctx: Context<CreateContributor>,
|
||||
conductor_chain: u16,
|
||||
|
@ -30,6 +34,7 @@ pub mod icco_contributor {
|
|||
conductor_address.try_into().expect("incorrect byte length");
|
||||
contributor.wormhole = wormhole;
|
||||
contributor.token_bridge = token_bridge;
|
||||
contributor.owner = ctx.accounts.owner.key();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -46,3 +51,8 @@ pub mod icco_contributor {
|
|||
instructions::sale_aborted(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Debug{
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ pub enum ContributorError {
|
|||
|
||||
#[account]
|
||||
pub struct Contributor {
|
||||
pub owner: Pubkey,
|
||||
pub conductor_chain: u16,
|
||||
pub conductor_address: [u8; 32],
|
||||
pub wormhole: Pubkey, // 32 bytes
|
|
@ -1,16 +1,17 @@
|
|||
import * as anchor from "@project-serum/anchor";
|
||||
import { Program } from "@project-serum/anchor";
|
||||
import { Icco } from "../target/types/icco";
|
||||
import { Contributor } from "../target/types/contributor";
|
||||
|
||||
|
||||
describe("icco", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.Icco as Program<Icco>;
|
||||
|
||||
it("Is initialized!", async () => {
|
||||
// Add your test here.
|
||||
const tx = await program.methods.initialize().rpc();
|
||||
console.log("Your transaction signature", tx);
|
||||
const program = anchor.workspace.contributor as Program<Contributor>;
|
||||
console.log(program.programId);
|
||||
|
||||
|
||||
it("creates a contributor", async () => {
|
||||
await program.methods.initialize().accounts({}).rpc();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue