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

[WIP] ERC20 Token Program #942

Closed
wants to merge 105 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
ffa6b60
Stash
dboehm-avalabs May 26, 2024
ebc78a2
Merge branch 'main' into TokenSwap
dboehm-avalabs May 26, 2024
9396155
remove loop
dboehm-avalabs May 26, 2024
62dfdd8
remove loop
dboehm-avalabs May 26, 2024
4522d61
Update state.rs
dboehm-avalabs May 26, 2024
d8a8978
Update state.rs
dboehm-avalabs May 26, 2024
37b74b9
fmt
dboehm-avalabs May 26, 2024
b646347
Update state.rs
dboehm-avalabs May 27, 2024
30d2344
Update lib.rs
dboehm-avalabs May 27, 2024
c825501
Update lib.rs
dboehm-avalabs May 28, 2024
7d3bb07
Update x/programs/test/programs/simple_token/src/lib.rs
dboehm-avalabs May 28, 2024
26d5b0d
Update x/programs/test/programs/simple_token/src/lib.rs
dboehm-avalabs May 28, 2024
4cebc7b
Update lib.rs
dboehm-avalabs May 28, 2024
4d97e49
Update lib.rs
dboehm-avalabs May 28, 2024
e73b8b8
stash
dboehm-avalabs May 28, 2024
0e8ceaf
BorshSerialize directly in state-keys macro
richardpringle May 29, 2024
6a3b486
Merge remote-tracking branch 'origin/multi-value-state-keys' into Tok…
dboehm-avalabs May 29, 2024
4ff28a2
stash
dboehm-avalabs May 29, 2024
4172c0d
Update lib.rs
dboehm-avalabs May 30, 2024
d5d56aa
Update state.rs
dboehm-avalabs May 30, 2024
623ba71
undo
dboehm-avalabs May 30, 2024
e811d33
undo
dboehm-avalabs May 30, 2024
27509db
move
dboehm-avalabs May 30, 2024
90805b6
Merge branch 'main' into TokenSwap
dboehm-avalabs May 30, 2024
1e63146
Update lib.rs
dboehm-avalabs May 30, 2024
e8ef714
Merge branch 'main' into TokenSwap
dboehm-avalabs May 30, 2024
88dda76
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 4, 2024
585fa3a
stash
dboehm-avalabs Jun 4, 2024
03c353d
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 4, 2024
ae79ef6
stash
dboehm-avalabs Jun 4, 2024
9703bfc
Cleanup Program Calls
dboehm-avalabs Jun 4, 2024
786c511
Update public_function.rs
dboehm-avalabs Jun 4, 2024
97bb1bc
Merge branch 'main' into FixProgramCalls
dboehm-avalabs Jun 4, 2024
26379bd
Merge branch 'main' into FixProgramCalls
dboehm-avalabs Jun 4, 2024
3634023
Merge branch 'FixProgramCalls' of github.com:ava-labs/hypersdk into F…
dboehm-avalabs Jun 4, 2024
16552c6
Update lib.rs
dboehm-avalabs Jun 4, 2024
fbe9009
Update public_function.rs
dboehm-avalabs Jun 4, 2024
d57436e
Merge branch 'FixProgramCalls' into TokenSwap
dboehm-avalabs Jun 4, 2024
7892923
Update program.rs
dboehm-avalabs Jun 4, 2024
f3d1fc5
add test
dboehm-avalabs Jun 5, 2024
c7be205
Update import_program.go
dboehm-avalabs Jun 5, 2024
6c70687
add test improvements
dboehm-avalabs Jun 5, 2024
6a56b65
Update test_util.go
dboehm-avalabs Jun 5, 2024
f8460d9
Update util.go
dboehm-avalabs Jun 5, 2024
abfccb7
Update test_util.go
dboehm-avalabs Jun 5, 2024
a252d28
linting
dboehm-avalabs Jun 5, 2024
a59a953
Merge branch 'main' into ImproveTestUtils
dboehm-avalabs Jun 5, 2024
df89323
merge
dboehm-avalabs Jun 5, 2024
e781677
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 5, 2024
d6d5a3d
linting
dboehm-avalabs Jun 5, 2024
93e8342
Update runtime_test.go
dboehm-avalabs Jun 5, 2024
f08c95a
Merge branch 'ImproveTestUtils' into TokenSwap
dboehm-avalabs Jun 5, 2024
b94c8ca
stash
dboehm-avalabs Jun 5, 2024
2fb2344
Reapply "[x/programs] Cleanup Program Calls (#1013)" (#1017)
dboehm-avalabs Jun 5, 2024
5cdd048
Switch To Address
dboehm-avalabs Jun 5, 2024
cf0b98d
stash
dboehm-avalabs Jun 5, 2024
80064bf
Create State Loader
dboehm-avalabs Jun 5, 2024
d9a4c82
lint
dboehm-avalabs Jun 5, 2024
aa2e79e
delete commitMutable
dboehm-avalabs Jun 5, 2024
4d9822c
Update simple.go
dboehm-avalabs Jun 5, 2024
ec99802
Update storage.go
dboehm-avalabs Jun 5, 2024
35c09c1
Merge branch 'ReworkState' into ReworkSimulator
dboehm-avalabs Jun 5, 2024
d40adbb
stash
dboehm-avalabs Jun 5, 2024
f7443b3
stash
dboehm-avalabs Jun 5, 2024
e84965a
fix prefix
dboehm-avalabs Jun 5, 2024
1b3184e
Update storage.go
dboehm-avalabs Jun 5, 2024
2bd1630
Update program.go
dboehm-avalabs Jun 5, 2024
4cd6db4
Merge branch 'ReworkSimulator' into SwitchProgramToAddress
dboehm-avalabs Jun 5, 2024
001e728
cleanup
dboehm-avalabs Jun 6, 2024
9ad6c48
Update lib.rs
dboehm-avalabs Jun 6, 2024
ee61417
Update import_program.go
dboehm-avalabs Jun 6, 2024
2ba65a9
Update lib.rs
dboehm-avalabs Jun 6, 2024
b327453
Update import_program_test.go
dboehm-avalabs Jun 6, 2024
c63c122
Update import_program_test.go
dboehm-avalabs Jun 6, 2024
5b8d5cd
Merge branch 'ReworkState' into ReworkSimulator
dboehm-avalabs Jun 6, 2024
d3bbca4
Merge branch 'ReworkSimulator' into SwitchProgramToAddress
dboehm-avalabs Jun 6, 2024
d6e591c
Update import_program_test.go
dboehm-avalabs Jun 6, 2024
41f6f98
lint
dboehm-avalabs Jun 6, 2024
53469c5
ignore broken tests
dboehm-avalabs Jun 6, 2024
c1dea43
fix simulator
dboehm-avalabs Jun 6, 2024
9a5c958
Update root.go
dboehm-avalabs Jun 6, 2024
d3a4c5a
Merge branch 'SwitchProgramToAddress' into ImproveTestUtils
dboehm-avalabs Jun 6, 2024
e7cc929
rewrite tests
dboehm-avalabs Jun 6, 2024
c6b2c8f
Update config.go
dboehm-avalabs Jun 6, 2024
2d7b996
Merge branch 'SwitchProgramToAddress' into ImproveTestUtils
dboehm-avalabs Jun 6, 2024
c845231
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 6, 2024
0236d49
Merge branch 'ImproveTestUtils' into TokenSwap
dboehm-avalabs Jun 6, 2024
804549f
stash
dboehm-avalabs Jun 6, 2024
cc7b2c3
rename
dboehm-avalabs Jun 6, 2024
05628ec
Merge branch 'SwitchProgramToAddress' into ImproveTestUtils
dboehm-avalabs Jun 6, 2024
3fb86c2
Merge branch 'ImproveTestUtils' into TokenSwap
dboehm-avalabs Jun 6, 2024
fac0819
cleanup
dboehm-avalabs Jun 6, 2024
d957941
use external calls
dboehm-avalabs Jun 6, 2024
112056c
Merge branch 'main' into SwitchProgramToAddress
dboehm-avalabs Jun 6, 2024
9d4b560
Merge branch 'SwitchProgramToAddress' into ImproveTestUtils
dboehm-avalabs Jun 6, 2024
f0a5ae4
Merge branch 'main' into ImproveTestUtils
dboehm-avalabs Jun 6, 2024
d6cb0c4
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 6, 2024
00490f2
Merge branch 'ImproveTestUtils' into TokenSwap
dboehm-avalabs Jun 6, 2024
c01d32e
cleanup
dboehm-avalabs Jun 6, 2024
3d7bab6
Update import_log_release.go
dboehm-avalabs Jun 6, 2024
d073b8c
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 12, 2024
1eab359
add debug tag
dboehm-avalabs Jun 12, 2024
3c91ab1
Merge branch 'main' into TokenSwap
dboehm-avalabs Jun 13, 2024
540d8a9
lint
dboehm-avalabs Jun 13, 2024
34cadcc
Update lib.rs
dboehm-avalabs Jun 13, 2024
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
23 changes: 23 additions & 0 deletions x/programs/rust/wasmlanche-sdk/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,29 @@ impl BorshSerialize for PrefixedBytes<'_> {
}
}

pub struct PrefixedMultiBytes<'a>(u8, &'a [&'a [u8]]);

impl<'a> PrefixedMultiBytes<'a> {
#[must_use]
pub fn new(prefix: u8, bytes: &'a [&'a [u8]]) -> Self {
Self(prefix, bytes)
}
}
dboehm-avalabs marked this conversation as resolved.
Show resolved Hide resolved

impl BorshSerialize for PrefixedMultiBytes<'_> {
fn serialize<W: std::io::prelude::Write>(&self, writer: &mut W) -> std::io::Result<()> {
let Self(prefix, bytes) = self;

let len = 1 + u32::try_from(bytes.iter().map(|byte| (byte.len())).sum::<usize>())
.map_err(|_| ErrorKind::InvalidData)?;

// TODO: just use bytemuck with the enum
writer.write_all(&len.to_le_bytes())?;
writer.write_all(&[*prefix])?;
bytes.iter().try_for_each(|buf| writer.write_all(buf))
}
}

#[derive(BorshSerialize)]
struct GetAndDeleteArgs<'a> {
key: PrefixedBytes<'a>,
Expand Down
14 changes: 14 additions & 0 deletions x/programs/test/programs/simple_token/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "simple_token"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasmlanche-sdk = { workspace = true }
borsh = { workspace = true }

[build-dependencies]
wasmlanche-sdk = { workspace = true, features = ["build"] }
dboehm-avalabs marked this conversation as resolved.
Show resolved Hide resolved
178 changes: 178 additions & 0 deletions x/programs/test/programs/simple_token/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
use wasmlanche_sdk::Context;
use wasmlanche_sdk::{public, state_keys, types::Address, Program};

const INITIAL_SUPPLY: u64 = 123456789;

/// The program state keys.
#[state_keys]
pub enum StateKey {
/// The total supply of the token. Key prefix 0x0.
TotalSupply,
/// The name of the token. Key prefix 0x1.
Name,
/// The symbol of the token. Key prefix 0x2.
Symbol,
/// The balance of the token by address. Key prefix 0x3 + address.
Balance(Address),

Allowance(Address, Address),

Owner,
}

pub fn get_owner(program: &Program<StateKey>) -> Address {
program
.state()
.get(StateKey::Owner)
.expect("failed to get total supply")
}

pub fn owner_check(program: &Program<StateKey>, actor: Address) {
assert!(
get_owner(program) == actor,
"caller is required to be owner"
)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could actually write an extension trait for the Context to call context.is_owner() directly.


/// Initializes the program with a name, symbol, and total supply.
#[public]
pub fn init(context: Context<StateKey>, name: String, symbol: String, owner: Address) {
let Context { program, actor } = context;

program
.state()
.store(StateKey::Owner, &actor)
.expect("failed to store total supply");

// set total supply
program
.state()
.store(StateKey::TotalSupply, &INITIAL_SUPPLY)
.expect("failed to store total supply");

// set token name
program
.state()
.store(StateKey::Name, &name)
.expect("failed to store coin name");

// set token symbol
program
.state()
.store(StateKey::Symbol, &symbol)
.expect("failed to store symbol");
}

/// Returns the total supply of the token.
#[public]
pub fn total_supply(context: Context<StateKey>) -> u64 {
let Context { program, .. } = context;
program
.state()
.get(StateKey::TotalSupply)
.unwrap_or_defaul()
}

/// Transfers balance from the token owner to the recipient.
#[public]
pub fn mint(context: Context<StateKey>, recipient: Address, amount: u64) -> bool {
let Context { program, actor } = context;
owner_check(&program, actor);
let balance = program
.state()
.get::<u64>(StateKey::Balance(recipient))
.unwrap_or_default();

program
.state()
.store(StateKey::Balance(recipient), &(balance + amount))
.expect("failed to store balance");

true
}

/// Burn the token from the recipient.
#[public]
pub fn burn(context: Context<StateKey>, recipient: Address) -> u64 {
let Context { program, actor } = context;
owner_check(&program, actor);
program
.state()
.delete::<u64>(StateKey::Balance(recipient))
.expect("failed to burn recipient tokens")
.expect("recipient balance not found")
}

/// Gets the balance of the recipient.
#[public]
pub fn balance_of(context: Context<StateKey>, account: Address) -> u64 {
let Context { program, .. } = context;
program
.state()
.get(StateKey::Balance(account))
.unwrap_or_default()
}

#[public]
pub fn allowance(context: Context<StateKey>, owner: Address, spender: Address) -> u64 {
let Context { program, .. } = context;
program
.state()
.get::<u64>(StateKey::Allowance([owner, spender]))
.unwrap_or_default()
}

#[public]
pub fn approve(context: Context<StateKey>, spender: Address, amount: u64) -> bool {
let Context { program, actor } = context;
assert_ne!(actor, spender, "actor and spender must be different");
program
.state()
.store(StateKey::Allowance([actor,spender]), &amount)
.expect("failed to store allowance");
true
}

/// Transfers balance from the sender to the the recipient.
#[public]
pub fn transfer(context: Context<StateKey>, recipient: Address, amount: u64) -> bool {
let Context { program, actor } = context;
let sender = actor;
assert_ne!(sender, recipient, "sender and recipient must be different");
dboehm-avalabs marked this conversation as resolved.
Show resolved Hide resolved

// ensure the sender has adequate balance
let sender_balance = program
.state()
.get::<u64>(StateKey::Balance(sender))
.expect("failed to update balance");

assert!(amount >= 0 && sender_balance >= amount, "invalid input");

let recipient_balance = program
.state()
.get::<u64>(StateKey::Balance(recipient))
.unwrap_or_default();

// update balances
program
.state()
.store(StateKey::Balance(sender), &(sender_balance - amount))
.expect("failed to store balance");

program
.state()
.store(StateKey::Balance(recipient), &(recipient_balance + amount))
.expect("failed to store balance");

true
}

#[public]
pub fn transfer_from(
context: Context<StateKey>,
sender: Address,
recipient: Address,
amount: u64,
) -> bool {
false
dboehm-avalabs marked this conversation as resolved.
Show resolved Hide resolved
}
Loading