-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1735 from dusk-network/issue-1630-contract-earns-fee
Economic Protocol scenario 3 - "contract earns fee"
- Loading branch information
Showing
31 changed files
with
1,565 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "charlie" | ||
version = "0.3.0" | ||
edition = "2021" | ||
resolver = "2" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "rlib"] | ||
|
||
[dependencies] | ||
execution-core = { version = "0.1.0", path = "../../execution-core" } | ||
rusk-abi = { version = "0.13.0-rc", path = "../../rusk-abi", features = ["dlmalloc"] } | ||
rkyv = { version = "0.7", default-features = false, features = ["size_32"] } | ||
bytecheck = { version = "0.6", default-features = false } | ||
dusk-bytes = "0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
TARGET_DIR:="../../target/dusk" | ||
|
||
all: wasm | ||
|
||
wasm: ## Generate the optimized WASM for the contract given | ||
@RUSTFLAGS="$(RUSTFLAGS) --remap-path-prefix $(HOME)= -C link-args=-zstack-size=65536" \ | ||
CARGO_TARGET_DIR=$(TARGET_DIR) \ | ||
cargo +dusk build \ | ||
--release \ | ||
--color=always \ | ||
-Z build-std=core,alloc,panic_abort \ | ||
-Z build-std-features=panic_immediate_abort \ | ||
--target wasm32-unknown-unknown | ||
clippy: | ||
|
||
test: | ||
|
||
.PHONY: all test wasm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
#![no_std] | ||
#![feature(arbitrary_self_types)] | ||
|
||
extern crate alloc; | ||
|
||
mod state; | ||
use state::Charlie; | ||
|
||
#[cfg(target_family = "wasm")] | ||
#[path = ""] | ||
mod wasm { | ||
use super::*; | ||
|
||
use rusk_abi::{ContractId, PaymentInfo}; | ||
|
||
#[no_mangle] | ||
static SELF_ID: ContractId = ContractId::uninitialized(); | ||
|
||
static mut STATE: Charlie = Charlie; | ||
|
||
#[no_mangle] | ||
unsafe fn pay(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |()| STATE.pay()) | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn pay_and_fail(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |()| STATE.pay_and_fail()) | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn earn(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |()| STATE.earn()) | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn earn_and_fail(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |()| STATE.earn_and_fail()) | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn earn_indirectly_and_fail(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |()| STATE.earn_indirectly_and_fail()) | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn subsidize(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |arg| STATE.subsidize(arg)) | ||
} | ||
|
||
const PAYMENT_INFO: PaymentInfo = PaymentInfo::Any(None); | ||
|
||
#[no_mangle] | ||
fn payment_info(arg_len: u32) -> u32 { | ||
rusk_abi::wrap_call(arg_len, |_: ()| PAYMENT_INFO) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
use alloc::vec::Vec; | ||
use dusk_bytes::Serializable; | ||
use execution_core::transfer::Stct; | ||
use execution_core::{BlsPublicKey, BlsSignature}; | ||
use rkyv::{Archive, Deserialize, Serialize}; | ||
use rusk_abi::TRANSFER_CONTRACT; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct Charlie; | ||
|
||
/// Subsidy a contract with a value. | ||
#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)] | ||
#[archive_attr(derive(bytecheck::CheckBytes))] | ||
pub struct Subsidy { | ||
/// Public key to which the subsidy will belong. | ||
pub public_key: BlsPublicKey, | ||
/// Signature belonging to the given public key. | ||
pub signature: BlsSignature, | ||
/// Value of the subsidy. | ||
pub value: u64, | ||
/// Proof of the `STCT` circuit. | ||
pub proof: Vec<u8>, | ||
} | ||
|
||
const SUBSIDY_MESSAGE_SIZE: usize = u64::SIZE + u64::SIZE; | ||
|
||
/// Return the digest to be signed in the `subsidize` function of a contract. | ||
#[must_use] | ||
pub fn subsidy_signature_message( | ||
counter: u64, | ||
value: u64, | ||
) -> [u8; SUBSIDY_MESSAGE_SIZE] { | ||
let mut bytes = [0u8; SUBSIDY_MESSAGE_SIZE]; | ||
|
||
bytes[..u64::SIZE].copy_from_slice(&counter.to_bytes()); | ||
bytes[u64::SIZE..].copy_from_slice(&value.to_bytes()); | ||
|
||
bytes | ||
} | ||
|
||
impl Charlie { | ||
fn gas_price() -> u64 { | ||
rusk_abi::call::<(), u64>(TRANSFER_CONTRACT, "gas_price", &()) | ||
.expect("Obtaining gas price should succeed") | ||
} | ||
|
||
/// calling this method will be paid by the contract | ||
pub fn pay(&mut self) { | ||
const ALLOWANCE: u64 = 40_000_000; | ||
let allowance = ALLOWANCE / Self::gas_price(); | ||
// this call is paid for by the contract, up to 'allowance' | ||
rusk_abi::set_allowance(allowance); | ||
} | ||
|
||
/// calling this method should be paid by the contract, yet it | ||
/// sets the allowance to a value too small to cover | ||
/// the execution cost, transaction will fail | ||
/// and contract balance won't be affected | ||
pub fn pay_and_fail(&mut self) { | ||
const ALLOWANCE: u64 = 8_000_000; | ||
let allowance = ALLOWANCE / Self::gas_price(); | ||
// this call is paid for by the contract, up to 'allowance' | ||
rusk_abi::set_allowance(allowance); | ||
} | ||
|
||
/// calling this method will cause the transaction fee to be | ||
/// increased so that contract can earn the difference between | ||
/// the contract's charge and the cost of gas actually spent | ||
pub fn earn(&mut self) { | ||
const CHARGE: u64 = 80_000_000; | ||
let charge = CHARGE / Self::gas_price(); | ||
// charging 'charge' for the call | ||
rusk_abi::set_charge(charge); | ||
} | ||
|
||
/// calling this method will cause the transaction fee to be | ||
/// increased, yet its sets the charge to a value too small to cover | ||
/// the actual execution cost, as a result the transaction will fail | ||
/// and contract balance won't be affected | ||
pub fn earn_and_fail(&mut self) { | ||
const CHARGE: u64 = 8_000_000; | ||
let charge = CHARGE / Self::gas_price(); | ||
// charging 'charge' for the call | ||
rusk_abi::set_charge(charge); | ||
} | ||
|
||
/// this method calls the `earn` method indirectly, and in such case, since | ||
/// charge is set by an indirectly called method, it won't have effect and | ||
/// contract balance won't be affected | ||
pub fn earn_indirectly_and_fail(&mut self) { | ||
rusk_abi::call::<_, ()>(rusk_abi::self_id(), "earn", &()) | ||
.expect("earn call should succeed"); | ||
} | ||
|
||
/// Subsidizes the contract with funds which can then be used | ||
/// for sponsoring free uses of other methods of this contract. | ||
/// Funds passed in this call will be used when granting allowances. | ||
/// The subsidy operation is similar to staking, yet the funds | ||
/// are deposited in this contract's "wallet". | ||
pub fn subsidize(&mut self, subsidy: Subsidy) { | ||
// verify the signature is over the correct digest | ||
// note: counter is always zero - make sure that this is safe | ||
let digest = subsidy_signature_message(0, subsidy.value).to_vec(); | ||
|
||
if !rusk_abi::verify_bls(digest, subsidy.public_key, subsidy.signature) | ||
{ | ||
panic!("Invalid signature!"); | ||
} | ||
|
||
// make call to transfer contract to transfer balance from the user to | ||
// this contract | ||
let transfer_module = TRANSFER_CONTRACT; | ||
|
||
let stct = Stct { | ||
module: rusk_abi::self_id().to_bytes(), | ||
value: subsidy.value, | ||
proof: subsidy.proof, | ||
}; | ||
|
||
// subsidizing self with 'subsidy.value' | ||
rusk_abi::call::<_, bool>(transfer_module, "stct", &stct) | ||
.expect("Sending note to contract should succeed"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.