Skip to content

Commit

Permalink
Merge branch 'main' into feat/da/exec/no-exec
Browse files Browse the repository at this point in the history
  • Loading branch information
popcnt1 authored Feb 24, 2025
2 parents 5a255b0 + 6a95b05 commit a159e51
Show file tree
Hide file tree
Showing 30 changed files with 576 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ sdk/typescript/src/generated/

# pnpm store
.pnpm-store/

rooch-book
11 changes: 6 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ proptest = "1.6.0"
proptest-derive = "0.3.0"
rayon = "1.5.2"
rand = "0.8.5"
rand_core = { version = "0.9.1", default-features = false }
rand_core = { version = "0.9.2", default-features = false }
reqwest = { version = "0.12", features = ["json", "stream"] }
schemars = { version = "0.8.21", features = ["either"] }
serde = { version = "1.0.218", features = ["derive", "rc"] }
Expand Down
14 changes: 14 additions & 0 deletions apps/minter_manager/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "minter_manager"
version = "0.0.1"

[dependencies]
MoveStdlib = { local = "../../frameworks/move-stdlib" }
MoveosStdlib = { local = "../../frameworks/moveos-stdlib" }
RoochFramework = { local = "../../frameworks/rooch-framework" }

[addresses]
std = "0x1"
moveos_std = "0x2"
rooch_framework = "0x3"
minter_manager = "_"
242 changes: 242 additions & 0 deletions apps/minter_manager/sources/MinterManager.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
module minter_manager::minter_manager {

// =========================== Packages ===========================
use moveos_std::event;
use moveos_std::signer;
use moveos_std::table;
use moveos_std::object::{Self, Object, ObjectID};
use rooch_framework::coin::{Self, Coin, CoinInfo};
use rooch_framework::account_coin_store;


// =========================== Constants ==========================
const ENOT_ADMIN: u64 = 120;
const ETREASURY_CAP_MANAGER_DESTROYED: u64 = 121;
const EMINTER_REVOKED: u64 = 122;


// ============================ Storage ===========================
struct TreasuryCapManager<phantom CoinType: key + store> has key {
admin: address,
coinInfoObj: Object<CoinInfo<CoinType>>,
revokedMinters: table::Table<ObjectID, bool>,
}

struct MinterCap<phantom CoinType: key + store> has key, store {
managerId: ObjectID,
}

#[event]
struct AdminTransferred has drop, copy {
prevAdmin: address,
newAdmin: address,
}

#[event]
struct TreasuryCapManagerSetup has drop, copy {
admin: address,
treasuryCapManagerId: ObjectID,
}

#[event]
struct TreasuryCapManagerDestroyed has drop, copy {
treasuryCapManagerId: ObjectID,
}

#[event]
struct MinterCapIssued has drop, copy {
recipient: address,
minterCapId: ObjectID,
}

#[event]
struct MinterCapRevoked has drop, copy {
minterCapId: ObjectID,
}

#[event]
struct MinterCapDestroyed has drop, copy {
minterCapId: ObjectID,
}


// =========================== Coin Admin Functions ===========================
public entry fun transferAdmin<CoinType: key + store>(
coinAdmin: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
newAdmin: address,
) {
let treasuryCapManager = object::borrow_mut(treasuryCapManagerObj);
assert!(signer::address_of(coinAdmin) == treasuryCapManager.admin, ENOT_ADMIN);
treasuryCapManager.admin = newAdmin;
event::emit(AdminTransferred { prevAdmin: signer::address_of(coinAdmin), newAdmin });
}

public entry fun setupTreasuryCapManager<CoinType: key + store>(
coinAdmin: &signer,
coinInfoObj: Object<CoinInfo<CoinType>>,
) {
let treasuryCapManager = TreasuryCapManager<CoinType> {
admin: signer::address_of(coinAdmin),
coinInfoObj,
revokedMinters: table::new(),
};
let treasuryCapManagerObject = object::new(treasuryCapManager);
let treasuryCapManagerId = object::id(&treasuryCapManagerObject);
object::to_shared(treasuryCapManagerObject);
event::emit(TreasuryCapManagerSetup { admin: signer::address_of(coinAdmin), treasuryCapManagerId });
}

public entry fun destroyTreasuryCapManager<CoinType: key + store>(
coinAdmin: &signer,
treasuryCapManagerId: ObjectID,
) {
let treasuryCapManager = object::remove(
object::take_object_extend<TreasuryCapManager<CoinType>>(treasuryCapManagerId)
);
assert!(signer::address_of(coinAdmin) == treasuryCapManager.admin, ENOT_ADMIN);
let TreasuryCapManager<CoinType> {
admin: _, coinInfoObj, revokedMinters,
} = treasuryCapManager;

table::drop(revokedMinters);
object::transfer(coinInfoObj, signer::address_of(coinAdmin));
event::emit(TreasuryCapManagerDestroyed { treasuryCapManagerId });
}

public entry fun issueMinterCap<CoinType: key + store>(
coinAdmin: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
recipient: address,
) {
let treasuryCapManager = object::borrow_mut(treasuryCapManagerObj);
assert!(signer::address_of(coinAdmin) == treasuryCapManager.admin, ENOT_ADMIN);
let minterCapObj = object::new(MinterCap<CoinType> {
managerId: object::id(treasuryCapManagerObj),
});
let minterCapId = object::id(&minterCapObj);
object::transfer(minterCapObj, recipient);
event::emit(MinterCapIssued { recipient, minterCapId });
}

public entry fun revokeMinterCap<CoinType: key + store>(
coinAdmin: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
minterCapId: ObjectID,
) {
let treasuryCapManager = object::borrow_mut(treasuryCapManagerObj);
assert!(signer::address_of(coinAdmin) == treasuryCapManager.admin, ENOT_ADMIN);
table::add(&mut treasuryCapManager.revokedMinters, minterCapId, true);
event::emit(MinterCapRevoked { minterCapId });
}

public entry fun destroyMinterCap<CoinType: key + store>(
_minter: &signer,
minterCapObj: Object<MinterCap<CoinType>>,
) {
let minterCapId = object::id(&minterCapObj);
let MinterCap<CoinType> { managerId: _ } = object::remove(minterCapObj);
event::emit(MinterCapDestroyed { minterCapId });
}


// =========================== Minter Functions ===========================
public entry fun mint<CoinType: key + store>(
_minter: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
minterCapObj: &mut Object<MinterCap<CoinType>>,
amount: u256,
recipient: address,
) {
let treasuryCapManagerId = object::id(treasuryCapManagerObj);
let treasuryCapManager = object::borrow_mut(treasuryCapManagerObj);
let minterCapId = object::id(minterCapObj);
let minterCap = object::borrow(minterCapObj);
assert!(
!table::contains(&treasuryCapManager.revokedMinters, minterCapId),
EMINTER_REVOKED,
);
assert!(
minterCap.managerId == treasuryCapManagerId,
ETREASURY_CAP_MANAGER_DESTROYED,
);
let coinToDeposit = coin::mint(&mut treasuryCapManager.coinInfoObj, amount);
account_coin_store::deposit(recipient, coinToDeposit);
}

public entry fun burnFromSigner<CoinType: key + store>(
burner: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
minterCapObj: &mut Object<MinterCap<CoinType>>,
amount: u256,
) {
let coinToBurn = account_coin_store::withdraw(burner, amount);
burn(burner, treasuryCapManagerObj, minterCapObj, coinToBurn);
}

public fun burn<CoinType: key + store>(
_sender: &signer,
treasuryCapManagerObj: &mut Object<TreasuryCapManager<CoinType>>,
minterCapObj: &mut Object<MinterCap<CoinType>>,
coinToBurn: Coin<CoinType>,
) {
let treasuryCapManagerId = object::id(treasuryCapManagerObj);
let treasuryCapManager = object::borrow_mut(treasuryCapManagerObj);
let minterCapId = object::id(minterCapObj);
let minterCap = object::borrow(minterCapObj);
assert!(
!table::contains(&treasuryCapManager.revokedMinters, minterCapId),
EMINTER_REVOKED,
);
assert!(
minterCap.managerId == treasuryCapManagerId,
ETREASURY_CAP_MANAGER_DESTROYED,
);
coin::burn(&mut treasuryCapManager.coinInfoObj, coinToBurn);
}


// =========================== Test ===========================

#[test_only]
use std::option;

#[test_only]
use std::string::utf8;

#[test_only]
struct FakeMoney has key, store {}

#[test(coinAdmin = @minter_manager)]
fun testIssueCoin(coinAdmin: &signer): ObjectID {
rooch_framework::genesis::init_for_test();
let coinInfoObj = coin::register_extend<FakeMoney>(
utf8(b"FakeMoney"),
utf8(b"FM"),
option::none(),
18, // decimal
);
let coinInfoObjId = object::id(&coinInfoObj);
object::transfer(coinInfoObj, signer::address_of(coinAdmin));
coinInfoObjId
}

#[test(coinAdmin = @minter_manager, to = @0x44cc)]
fun testNormalMint(coinAdmin: &signer, to: &signer) {
let coinInfoObjId = testIssueCoin(coinAdmin);
let coinInfoObjMut = object::borrow_mut_object<CoinInfo<FakeMoney>>(
coinAdmin, coinInfoObjId
);
let coinToDeposit = coin::mint(coinInfoObjMut, 1000000);
account_coin_store::deposit(signer::address_of(to), coinToDeposit);

}

#[test(coinAdmin = @minter_manager)]
fun testSetupTreasury(coinAdmin: &signer) {
let coinInfoObjId = testIssueCoin(coinAdmin);
let coinInfoObj = object::take_object(coinAdmin, coinInfoObjId);
setupTreasuryCapManager<FakeMoney>(coinAdmin, coinInfoObj);
}

}
23 changes: 23 additions & 0 deletions apps/minter_manager/sources/coins/usdt_m.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

module minter_manager::usdt_m {
use std::option::some;
use std::string;
use std::string::utf8;
use moveos_std::signer::module_signer;
use minter_manager::minter_manager::setupTreasuryCapManager;
use rooch_framework::coin;

struct USDT has key, store{}

const COIN_URL: vector<u8> = b"<svg id=\"Layer_1\" data-name=\"Layer 1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 339.43 295.27\"><title>tether-usdt-logo</title><path d=\"M62.15,1.45l-61.89,130a2.52,2.52,0,0,0,.54,2.94L167.95,294.56a2.55,2.55,0,0,0,3.53,0L338.63,134.4a2.52,2.52,0,0,0,.54-2.94l-61.89-130A2.5,2.5,0,0,0,275,0H64.45a2.5,2.5,0,0,0-2.3,1.45h0Z\" style=\"fill:#50af95;fill-rule:evenodd\"/><path d=\"M191.19,144.8v0c-1.2.09-7.4,0.46-21.23,0.46-11,0-18.81-.33-21.55-0.46v0c-42.51-1.87-74.24-9.27-74.24-18.13s31.73-16.25,74.24-18.15v28.91c2.78,0.2,10.74.67,21.74,0.67,13.2,0,19.81-.55,21-0.66v-28.9c42.42,1.89,74.08,9.29,74.08,18.13s-31.65,16.24-74.08,18.12h0Zm0-39.25V79.68h59.2V40.23H89.21V79.68H148.4v25.86c-48.11,2.21-84.29,11.74-84.29,23.16s36.18,20.94,84.29,23.16v82.9h42.78V151.83c48-2.21,84.12-11.73,84.12-23.14s-36.09-20.93-84.12-23.15h0Zm0,0h0Z\" style=\"fill:#fff;fill-rule:evenodd\"/></svg>";

fun init() {
let coin_info_obj = coin::register_extend<USDT>(
string::utf8(b"USDT From Mesion Fi"),
string::utf8(b"USDT.M"),
some(utf8(COIN_URL)),
6,
);
setupTreasuryCapManager(&module_signer<USDT>(), coin_info_obj)
}
}
6 changes: 6 additions & 0 deletions apps/minter_manager/test/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Export your address here
export MINTER_MANAGER="0x0af854fcad035f4134636ff2d7fa22591f8ff2f264f354ac04e53da06e318529" # address #1

# Deploy minter_manager package
cd minter_manager
rooch move publish --named-addresses minter_manager="$MINTER_MANAGER"
14 changes: 13 additions & 1 deletion crates/rooch-executor/src/actor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use rooch_genesis::FrameworksGasParameters;
use rooch_store::state_store::StateStore;
use rooch_store::RoochStore;
use rooch_types::address::{BitcoinAddress, MultiChainAddress};
// use rooch_types::bitcoin::transaction_validator::TransactionValidator as L1TransactionValidator;
use rooch_types::bitcoin::BitcoinModule;
use rooch_types::framework::auth_validator::{
AuthValidatorCaller, BuiltinAuthValidator, TxValidateResult,
Expand Down Expand Up @@ -236,9 +237,19 @@ impl ExecutorActor {
let tx_hash = l1_tx.tx_hash();
let tx_size = l1_tx.tx_size();
let ctx = TxContext::new_system_call_ctx(tx_hash, tx_size);
//TODO we should call the contract to validate the l1 tx has been executed
let result = match RoochMultiChainID::try_from(l1_tx.chain_id.id())? {
RoochMultiChainID::Bitcoin => {
//L1 tx validate first launches the contract, then opens the Rust code
// // Validate the l1 tx before execution via contract,
// let l1_tx_validator = self.as_module_binding::<L1TransactionValidator>();
// let tx_validator_result = l1_tx_validator
// .validate_l1_tx(ctx, tx_hash, vec![])
// .map_err(Into::into)?;
// // If the l1 tx already execute, skip the tx.
// if !tx_validator_result {
// return Err(RoochError::L1TxAlreadyExecuted);
// }

let action = VerifiedMoveAction::Function {
call: BitcoinModule::create_execute_l1_tx_call(l1_tx.block_hash, l1_tx.txid)?,
bypass_visibility: true,
Expand All @@ -249,6 +260,7 @@ impl ExecutorActor {
action,
))
}
// _id => Err(RoochError::InvalidChainID),
id => Err(anyhow::anyhow!("Chain {} not supported yet", id)),
};

Expand Down
Loading

0 comments on commit a159e51

Please sign in to comment.