|
| 1 | +#![feature(maybe_uninit_uninit_array)] |
| 2 | +#![no_std] |
| 3 | +#![no_main] |
| 4 | + |
| 5 | +use hooks_rs::*; |
| 6 | + |
| 7 | +const ACCOUNT_SLOT_ID: u32 = 1; |
| 8 | +const ACCOUNT_BALANCE_SLOT_ID: u32 = 3; |
| 9 | + |
| 10 | +#[no_mangle] |
| 11 | +pub extern "C" fn cbak(_: u32) -> i64 { |
| 12 | + 0 |
| 13 | +} |
| 14 | + |
| 15 | +// Example: https://github.com/Xahau/TreasuryHook/blob/ac8e2f7db4b687450d9ca1cba412bfac3b1a87bc/treasuryInvoke.c#L150-L153 |
| 16 | +#[no_mangle] |
| 17 | +pub extern "C" fn hook(_: u32) -> i64 { |
| 18 | + // Every hook needs to import guard function |
| 19 | + // and use it at least once |
| 20 | + max_iter(1); |
| 21 | + // https://explorer.xahau-test.net/r3zEReqN3Ge3g1GXUThuVSrn4dM8xpoA7i |
| 22 | + // 579CA1B8B51227C2E40AB3217D9421EFB13B1364 |
| 23 | + let account_id: [u8; ACC_ID_LEN] = [ |
| 24 | + 0x57, 0x9C, 0xA1, 0xB8, 0xB5, 0x12, 0x27, 0xC2, 0xE4, 0x0A, 0xB3, 0x21, 0x7D, 0x94, 0x21, |
| 25 | + 0xEF, 0xB1, 0x3B, 0x13, 0x64, |
| 26 | + ]; |
| 27 | + let keylet_payload = KeyletAccount::new(&account_id).build(); |
| 28 | + let account_keylet = util_keylet(keylet_payload).unwrap_line_number(); |
| 29 | + |
| 30 | + // Will throw if account does not exist, but we know the account exists, so it shouldn't throw |
| 31 | + slot_set(&account_keylet, ACCOUNT_SLOT_ID).unwrap_line_number(); |
| 32 | + |
| 33 | + // Does not exist on Xahau testnet |
| 34 | + // Check existence on https://explorer.xahau-test.net/rDAFKjBukJ6r197ZPH7W5QkJDqVQLZhxud |
| 35 | + let nonexistent_account_id: [u8; ACC_ID_LEN] = [ |
| 36 | + 0x8d, 0xff, 0x79, 0x78, 0xae, 0xb4, 0x94, 0x45, 0xc7, 0xcf, 0x8c, 0x93, 0x3a, 0x4a, 0xdf, |
| 37 | + 0xa5, 0x23, 0x14, 0x06, 0xfa, |
| 38 | + ]; |
| 39 | + let nonexistent_account_keylet = |
| 40 | + util_keylet(KeyletAccount::new(&nonexistent_account_id).build()).unwrap_line_number(); |
| 41 | + |
| 42 | + match slot_set(&nonexistent_account_keylet, 2) { |
| 43 | + Ok(_) => { |
| 44 | + // This should not happen |
| 45 | + rollback( |
| 46 | + b"Should not be able to set slot for nonexistent account", |
| 47 | + -2, |
| 48 | + ); |
| 49 | + } |
| 50 | + Err(e) => { |
| 51 | + // This is expected |
| 52 | + if e != Error::DoesntExist { |
| 53 | + // This should not happen |
| 54 | + rollback( |
| 55 | + b"Should not be able to set slot for nonexistent account", |
| 56 | + -3, |
| 57 | + ); |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + // First way to get the account balance |
| 63 | + slot_subfield(ACCOUNT_SLOT_ID, FieldId::Balance, ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number(); |
| 64 | + let account_balance_slot = slot::<XFL_LEN>(ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number(); |
| 65 | + // This should be 1000000000000000*10^(-6) |
| 66 | + let xfl_balance_0 = XFL::from_sto(&account_balance_slot).unwrap_line_number(); |
| 67 | + let i64_balance_0 = xfl_balance_0.to_int64(0, false).unwrap_line_number(); |
| 68 | + |
| 69 | + // Another way to get the account balance |
| 70 | + // See https://github.com/Xahau/xahaud/blob/0b675465b4e038e6080146043ad7fb2bfaf1a53e/src/ripple/app/hook/impl/applyHook.cpp#L2790-L2797 |
| 71 | + // balance is multiplied by 10^-6 (drops decimals) again for some reason when using slot_float |
| 72 | + // so this should be 1000000000000000*10^(-12) |
| 73 | + let xfl_balance_1 = slot_float(ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number(); |
| 74 | + |
| 75 | + // 10 * (10^5) = 10^6 |
| 76 | + let mul_factor = XFL::new(5, 10).unwrap_line_number(); |
| 77 | + let adjusted_xfl_balance_1 = (xfl_balance_1 * mul_factor).unwrap_line_number(); |
| 78 | + |
| 79 | + let _ = trace_float(b"mul_factor", mul_factor); |
| 80 | + let _ = trace_float(b"xfl_balance_0", xfl_balance_0); |
| 81 | + let _ = trace_float(b"adjusted_xfl_balance_1", adjusted_xfl_balance_1); |
| 82 | + |
| 83 | + // Assert same (equality is overloaded) |
| 84 | + if xfl_balance_0 != adjusted_xfl_balance_1 { |
| 85 | + rollback(b"xfl_balance_0 != adjusted_xfl_balance_1", -4); |
| 86 | + } |
| 87 | + |
| 88 | + accept(b"passing", i64_balance_0); |
| 89 | +} |
0 commit comments