ab_system_contract_code/
lib.rs1#![no_std]
2
3use ab_contracts_common::env::{Env, MethodContext};
4use ab_contracts_common::{ContractError, MAX_CODE_SIZE};
5use ab_contracts_macros::__private::Address;
6use ab_contracts_macros::contract;
7use ab_io_type::trivial_type::TrivialType;
8use ab_io_type::variable_bytes::VariableBytes;
9use ab_system_contract_address_allocator::AddressAllocatorExt;
10
11#[derive(Debug, Copy, Clone, TrivialType)]
12#[repr(C)]
13pub struct Code;
14
15#[contract]
16impl Code {
17 #[update]
19 pub fn deploy(
20 #[env] env: &mut Env<'_>,
21 #[input] code: &VariableBytes<MAX_CODE_SIZE>,
22 ) -> Result<Address, ContractError> {
23 let new_contract_address = env.address_allocator_allocate_address(
24 MethodContext::Replace,
25 Address::system_address_allocator(env.shard_index()),
26 )?;
27
28 env.code_store(
29 MethodContext::Replace,
30 env.own_address(),
31 &new_contract_address,
32 code,
33 )?;
34
35 Ok(new_contract_address)
36 }
37
38 #[update]
43 pub fn store(
44 #[env] env: &mut Env<'_>,
45 #[slot] (address, contract_code): (&Address, &mut VariableBytes<MAX_CODE_SIZE>),
46 #[input] new_code: &VariableBytes<MAX_CODE_SIZE>,
47 ) -> Result<(), ContractError> {
48 if !(env.caller() == Address::NULL
52 || env.caller() == env.own_address()
53 || env.caller() == address)
54 {
55 return Err(ContractError::Forbidden);
56 }
57
58 if !contract_code.copy_from(new_code) {
59 return Err(ContractError::BadInput);
60 }
61
62 Ok(())
63 }
64
65 #[view]
67 pub fn read(
68 #[slot] contract_code: &VariableBytes<MAX_CODE_SIZE>,
69 #[output] code: &mut VariableBytes<MAX_CODE_SIZE>,
70 ) -> Result<(), ContractError> {
71 if code.copy_from(contract_code) {
72 Ok(())
73 } else {
74 Err(ContractError::BadInput)
75 }
76 }
77}