followup update for ido -> adding ipfs bcmr placeholder

This commit is contained in:
Hossein Zoda 2026-05-11 19:04:13 +03:00
parent 335818460f
commit f8ddac6ec3

View file

@ -18,6 +18,10 @@ use std::collections::{HashMap};
use sqlx::{Row, SqlitePool}; use sqlx::{Row, SqlitePool};
use crate::db::blob::{ToBlob, blob_to_display_hex}; use crate::db::blob::{ToBlob, blob_to_display_hex};
const BCMR_SIGNATURE: &[u8] = &[
0x6a, 0x04, 0x42, 0x43, 0x4d, 0x52, 0x20,
];
const ITEM_TYPE_BITS: u8 = 0x0f; const ITEM_TYPE_BITS: u8 = 0x0f;
const DISTRIBUTOR_FLAG_IS_REFUND: u8 = 0x10; const DISTRIBUTOR_FLAG_IS_REFUND: u8 = 0x10;
const CONFIRMATION_NFT_FLAG_IS_REFUND: u8 = 0x10; const CONFIRMATION_NFT_FLAG_IS_REFUND: u8 = 0x10;
@ -81,17 +85,45 @@ static LAUNCHER_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c000
static DISTRIBUTOR_DEPLOY_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0009d00c852c88852c9529d00cf517f77567f758100ce01207f7551ce01207f75788851cf517f755f84538851cf517f7551ca51ca82770136940120947f7701207f750000537960840100876451cf517f77567f75817b757c51cf577f77587f758177687800a2697600a26952d352d051d0949d587a810000567901208401008764527900a26951c6765479950400e1f50596537a757c6b7c6c765379947b757c53cc5279a26953d1008854cc5379a26954d10088756753d05379950400e1f505967b757c53d0527994777600a06353d3789d53d153ce886753d10088687800a06354d352799d54d153ce886754d100886868547900a06302aa20012057797e5f797eaa7e01877e51cd8851d1587988565551807e5c797e597956799356807e51d28851d3009d55d351d09d55d152ce8802aa20525152807e60797eaa7e01877e55cd8855d200886751d351d09d51d152ce8802aa20012057797e5e797eaa7e01877e51cd8851d20088687600a06302aa2001205b797e5e797eaa7e01877e53cd886753cd016a88687c00a06302aa2001205b797e5d797eaa7e01877e54cd886754cd016a886800cf577f77547f75817651a06300cf517f7500cf517f77567f757e788c54807e00cf5b7f77587f758153799358807e00cf01137f77587f757e00cf011b7f77587f758155799358807e00d28800ce00d18800c700cd8800d000d39d52cf52d28852ce52d18852c752cd88675500cf517f77567f757e00cf5b7f77587f758153799358807e00cf01137f77587f757e00cf011b7f77587f758155799358807e00d28800d158798800d3009d02aa2001205b797e5e797eaa7e01877e00cd8852d100885457790120840100876475536876ce59798876cf517f755f845488756855557a00a063755668c4789e6376d10088c4788b9d686d6d6d6d6d6d6d7551").unwrap()); static DISTRIBUTOR_DEPLOY_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0009d00c852c88852c9529d00cf517f77567f758100ce01207f7551ce01207f75788851cf517f755f84538851cf517f7551ca51ca82770136940120947f7701207f750000537960840100876451cf517f77567f75817b757c51cf577f77587f758177687800a2697600a26952d352d051d0949d587a810000567901208401008764527900a26951c6765479950400e1f50596537a757c6b7c6c765379947b757c53cc5279a26953d1008854cc5379a26954d10088756753d05379950400e1f505967b757c53d0527994777600a06353d3789d53d153ce886753d10088687800a06354d352799d54d153ce886754d100886868547900a06302aa20012057797e5f797eaa7e01877e51cd8851d1587988565551807e5c797e597956799356807e51d28851d3009d55d351d09d55d152ce8802aa20525152807e60797eaa7e01877e55cd8855d200886751d351d09d51d152ce8802aa20012057797e5e797eaa7e01877e51cd8851d20088687600a06302aa2001205b797e5e797eaa7e01877e53cd886753cd016a88687c00a06302aa2001205b797e5d797eaa7e01877e54cd886754cd016a886800cf577f77547f75817651a06300cf517f7500cf517f77567f757e788c54807e00cf5b7f77587f758153799358807e00cf01137f77587f757e00cf011b7f77587f758155799358807e00d28800ce00d18800c700cd8800d000d39d52cf52d28852ce52d18852c752cd88675500cf517f77567f757e00cf5b7f77587f758153799358807e00cf01137f77587f757e00cf011b7f77587f758155799358807e00d28800d158798800d3009d02aa2001205b797e5e797eaa7e01877e00cd8852d100885457790120840100876475536876ce59798876cf517f755f845488756855557a00a063755668c4789e6376d10088c4788b9d686d6d6d6d6d6d6d7551").unwrap());
static DISTRIBUTOR_REFUND_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0009d00ce01207f7551ce01207f75788851cf517f755f84538851ca51ca82770136940120947f7701207f7551cf517f75760120840100876451cc51c6a26951d100886751d352d09d51d152ce886802aa200120537a7e55797eaa7e01877e51cd8800cf577f77547f75817651a06300cf517f7500cf517f77567f757e788c54807e00cf5b7f77587f757e00cf01137f77587f757e00cf011b7f77587f757e00d28800ce00d18800c700cd88c4529e6352d10088c4539d686755608500cf517f77567f757e00cf5b7f77587f757e00cf01137f77587f757e00cf011b7f77587f757e00d288527900d18800d3009d02aa20012055797e56797eaa7e01877e00cd8852d100885352790120840100876475526876ce54798876cf517f755f845488c4539e6353d10088c4549d6875686d6d7551").unwrap()); static DISTRIBUTOR_REFUND_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0009d00ce01207f7551ce01207f75788851cf517f755f84538851ca51ca82770136940120947f7701207f7551cf517f75760120840100876451cc51c6a26951d100886751d352d09d51d152ce886802aa200120537a7e55797eaa7e01877e51cd8800cf577f77547f75817651a06300cf517f7500cf517f77567f757e788c54807e00cf5b7f77587f757e00cf01137f77587f757e00cf011b7f77587f757e00d28800ce00d18800c700cd88c4529e6352d10088c4539d686755608500cf517f77567f757e00cf5b7f77587f757e00cf01137f77587f757e00cf011b7f77587f757e00d288527900d18800d3009d02aa20012055797e56797eaa7e01877e00cd8852d100885352790120840100876475526876ce54798876cf517f755f845488c4539e6353d10088c4549d6875686d6d7551").unwrap());
static EXECUTION_FEE_PAYOUT_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0ce00ce01207f758800cf517f755f84528800cf577f77547f758151a169c0cf517f7701207f7502aa2001207b7e7b7eaa7e01877e52cd8852ccc0c6a2").unwrap()); static EXECUTION_FEE_PAYOUT_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0ce00ce01207f758800cf517f755f84528800cf577f77547f758151a169c0cf517f7701207f7502aa2001207b7e7b7eaa7e01877e52cd8852ccc0c6a2").unwrap());
static OFFERING_INITIATOR_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0c9009dc0c85b79c8885a79c9577a9d5979ce827701209d567900a263c0c85b79c8885a79c957799d68c0c800d1788800d2578800d3009d00cd5a7a88c08bc0c878c88876c9547a9d76ca827778ca7853947f77527f75817bca7b53945279947f777c7f75c05293c0c878c88876c9557a9d76ca827778ca7853947f77527f75817bca7b53945279947f777c7f75c05393c0c878c88876c9567a9d76ca827778ca7853947f77527f75815178529302ff00a063755367785293014ba063755268685379ca537a5394537a947b947f7702aa20525352807e5b797e7b7eaa7e01877e54cd8854cc7cc6a26954d10088c05493c0c878c88876c9567a9d76ca827778ca7853947f77527f75815178529302ff00a063755367785293014ba063755268685379ca537a5394537a947b947f7702aa20525352807e5a797e7b7eaa7e01877e55cd8855cc7cc6a26955d100885779d07600a0690100557a7e04000000007e51d28851d15479527e8851d3789d51cd02aa20547aaa7e01877e885153d28853d153798853d3009d53cd02aa20537aaa7e01877e8802aa20525352807e567a7eaa7e01877e52cd8852cc5579c6a26952d1557ace8852d39d52d20088c05593c0c878c88876c9537a9d76c7827778c77853947f77527f75817bc77b53945279947f777c7f7576827700a0766378517f75016a8777686356cd78886756cd016a886856d1008857d100876457d101207f7552798791696857cd567f75066a0442434d52879169c4589e6358d100876458d101207f7552798791696858cd567f75066a0442434d52879169c4599e6359d100876459d101207f7552798791696859cd567f75066a0442434d52879169c45a9e635ad10087645ad101207f755279879169685acd567f75066a0442434d52879169c45b9e635bd10087645bd101207f755279879169685bcd567f75066a0442434d52879169c45c9d686868686d6d51").unwrap()); static OFFERING_INITIATOR_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0c9009dc0c85b79c8885a79c9577a9d5979ce827701209d567900a263c0c85b79c8885a79c957799d68c0c800d1788800d2578800d3009d00cd5a7a88c08bc0c878c88876c9547a9d76ca827778ca7853947f77527f75817bca7b53945279947f777c7f75c05293c0c878c88876c9557a9d76ca827778ca7853947f77527f75817bca7b53945279947f777c7f75c05393c0c878c88876c9567a9d76ca827778ca7853947f77527f75815178529302ff00a063755367785293014ba063755268685379ca537a5394537a947b947f7702aa20525352807e5b797e7b7eaa7e01877e54cd8854cc7cc6a26954d10088c05493c0c878c88876c9567a9d76ca827778ca7853947f77527f75815178529302ff00a063755367785293014ba063755268685379ca537a5394537a947b947f7702aa20525352807e5a797e7b7eaa7e01877e55cd8855cc7cc6a26955d100885779d07600a0690100557a7e04000000007e51d28851d15479527e8851d3789d51cd02aa20547aaa7e01877e885153d28853d153798853d3009d53cd02aa20537aaa7e01877e8802aa20525352807e567a7eaa7e01877e52cd8852cc5579c6a26952d1557ace8852d39d52d20088c05593c0c878c88876c9537a9d76c7827778c77853947f77527f75817bc77b53945279947f777c7f7576827700a06376517f75768176014b9f788b547982779f9a635279788b7f77537a757c6b7c6c5279517f757b757c6878016a8764016a537a757c6b7c6c686d67016a776856cd8856d1008857d100876457d101207f75788791696857cd567f75066a0442434d52879169c4589e6358d100876458d101207f75788791696858cd567f75066a0442434d52879169c4599e6359d100876459d101207f75788791696859cd567f75066a0442434d52879169c45a9e635ad10087645ad101207f7578879169685acd567f75066a0442434d52879169c45b9e635bd10087645bd101207f7578879169685bcd567f75066a0442434d52879169c45c9d686868686d7551").unwrap());
static OFFERING_INTEGRATED_TIMELOCKED_P2NFTH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0cf527f7701207f75c0cf01227f77815479ce01207f757b88537acf567f75817600a0699f6978ce7bcf7eaa88c0cf517f77517f7581c0c85279c8887cc99c").unwrap()); static OFFERING_INTEGRATED_TIMELOCKED_P2NFTH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0cf527f7701207f75c0cf01227f77815479ce01207f757b88537acf567f75817600a0699f6978ce7bcf7eaa88c0cf517f77517f7581c0c85279c8887cc99cs").unwrap());
static IDO_INITIATOR_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0ce827701209dc0cf827700a0695579827701209dc0c85779c8885679c99dc0c85779c8885679c99d5479529376ca827778ca7853947f77527f75817bca7b53945279947f777c7f7501157f7701207f75c0cec0cf7eaa88547ac852d1827701209d52d300a06902aa20c101147f755479827751807e54797e5379827751807e537a7e01207e7b7e01207e52d17e01207e547a7e587e52d358807e537a7eaa7e01877e57cd8857ccc0c6a26957d1c0ce8857d2c0cf8857d3c0d09d02aa20525752807e7b7eaa7e01877e7658cd8858cc02e803a26958d1008859cd8859cc78c6a26959d178ce8859d278cf8859d37cd09c").unwrap()); static IDO_INITIATOR_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0ce827701209dc0cf827700a0695579827701209dc0c85779c8885679c99dc0c85779c8885679c99d5479529376ca827778ca7853947f77527f75817bca7b53945279947f777c7f7501157f7701207f75c0cec0cf7eaa88547ac852d1827701209d52d300a06902aa20c101147f755479827751807e54797e5379827751807e537a7e01207e7b7e01207e52d17e01207e547a7e587e52d358807e537a7eaa7e01877e57cd8857ccc0c6a26957d1c0ce8857d2c0cf8857d3c0d09d02aa20525752807e7b7eaa7e01877e7658cd8858cc02e803a26958d1008859cd8859cc78c6a26959d178ce8859d278cf8859d37cd09c").unwrap());
static IDO_POSTLAUNCH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("5879009c63c0009dc0c9009e69c0cdc0c788c0ccc0c6a269c0d1c0ce88c0d3c0d09dc0d2c0cf8802aa20520052807e597a7eaa7e01877ec0c851c88851c9589d7651cd8851cc51c6a26951d151ce8851d351d09dc0c852c88852c9599d52cd8852cc52c6a26952d152ce8852d352d09dc353a06353ce0088c3549d6853d10088c4549d6d6d6d6d51675879519c63c0009dc0c9009dc0cdc0c788c0d1c0ce88c0d3c0d09dc0d2c0cf88c0c852c88852c9529d52cd52c78852cc52c6a26952d152ce8852d352d09d02aa200120c0cec0cf7eaa7e587a7eaa7e01877e00005376c75479876376ce59798763527978d093537a757c6b7c6c6776ce0088686ec6937b757c6776ce008868768bc378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c3789d6868686868686868c0ccc0c6547a93a269c0c851c88851c9519d51cd51c78851cc51c6a26951d0537a937600a06351d159798851d378a26951d200886751d100886853d10088c4549d6d6d6d6d6d6d5167587a529dc0009dc0c9009d5379827701209d53ce567a8853cf517f755f845588c0c653cf577f77587f7581a269c0c851c88851c9519d53cf5f7f77587f75817600a06351d078a2696851d000a06351ce5679886851cf0088c0c852c88852c9529d52ce567988000053cf517f75608401008763557981537994765679950400e1f505967652d0a06352d07768765679950500e87648179653cf01177f77587f758194760500e8764817955779967802e803a27800a09a6378567a757c6b7c6b7c6b7c6b7c6c6c6c6c765379a16376557a757c6b7c6b7c6b7c6c6c6c675279557a757c6b7c6b7c6b7c6c6c6c68686d6d68c0c651c69352c69352799451d052d093527994537900a0537900a09a6302aa2005746376a914000114807e2b88ac67c0d1c0ce88c25288c0cdc0c788c0c6c0d095c0c6c0cc9490539502e80396c0cc7c94c0d3957ca2687eaa7e01877e00cd8800cc54799d00d15a798800d353799d00d20088096a0653554d4d4f4e14000114807e51cd8851cc009d51d100886700d1008800cd016a8851d1008851cd016a886802aa2001205a7a7e5b7a7eaa7e01877e52cd8852cc7ba2697600a06352d378a26952d158798852d200886752d100886853d10088c4549d6d6d6d6d75516868").unwrap()); static IDO_POSTLAUNCH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("5879009c63c0009dc0c9009e69c0cdc0c788c0ccc0c6a269c0d1c0ce88c0d3c0d09dc0d2c0cf8802aa20520052807e597a7eaa7e01877ec0c851c88851c9589d7651cd8851cc51c6a26951d151ce8851d351d09dc0c852c88852c9599d52cd8852cc52c6a26952d152ce8852d352d09dc353a06353ce0088c3549d6853d10088c4549d6d6d6d6d51675879519c63c0009dc0c9009dc0cdc0c788c0d1c0ce88c0d3c0d09dc0d2c0cf88c0c852c88852c9529d52cd52c78852cc52c6a26952d152ce8852d352d09d02aa200120c0cec0cf7eaa7e587a7eaa7e01877e00005376c75479876376ce59798763527978d093537a757c6b7c6c6776ce0088686ec6937b757c6776ce008868768bc378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c378a06376c75579876376ce5a798763537978d093547a757c6b7c6b7c6c6c6776ce008868527978c693537a757c6b7c6c6776ce008868768b77c3789d6868686868686868c0ccc0c6547a93a269c0c851c88851c9519d51cd51c78851cc51c6a26951d0537a937600a06351d159798851d378a26951d200886751d100886853d10088c4549d6d6d6d6d6d6d5167587a529dc0009dc0c9009d5379827701209d53ce567a8853cf517f755f845588c0c653cf577f77587f7581a269c0c851c88851c9519d53cf5f7f77587f75817600a06351d078a2696851d000a06351ce5679886851cf0088c0c852c88852c9529d52ce567988000053cf517f75608401008763557981537994765679950400e1f505967652d0a06352d07768765679950500e87648179653cf01177f77587f758194760500e8764817955779967802e803a27800a09a6378567a757c6b7c6b7c6b7c6b7c6c6c6c6c765379a16376557a757c6b7c6b7c6b7c6c6c6c675279557a757c6b7c6b7c6b7c6c6c6c68686d6d68c0c651c69352c69352799451d052d093527994537900a0537900a09a6302aa2005746376a914000114807e2b88ac67c0d1c0ce88c25288c0cdc0c788c0c6c0d095c0c6c0cc9490539502e80396c0cc7c94c0d3957ca2687eaa7e01877e00cd8800cc54799d00d15a798800d353799d00d20088096a0653554d4d4f4e14000114807e51cd8851cc009d51d100886700d1008800cd016a8851d1008851cd016a886802aa2001205a7a7e5b7a7eaa7e01877e52cd8852cc7ba2697600a06352d378a26952d158798852d200886752d100886853d10088c4549d6d6d6d6d75516868").unwrap());
static IDO_PREINIT_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0519dc0c800c88800c9529dc0c852c88852c9539dc0c853c88853c9549dc0c854c88854c9559dc0c855c88855c9569dc0c856c88856c9579d5979009e63c0c858c88858c9599d67c0c858c88858c9599d68c0c857c88857c9589d567981009c5a79009c9b587981009c9b63c0d1008852cd00c78852d1008853cd52c78853d1008854cd53c78854d1008855cd54c78855d1008856cd55c78856d1008857cd56c78857d100885979009e6359cd58c78859cc58c6a26959d158ce8859d358d09d59d258cf8867567981009e5979009e9a6459cd58c78859d10088686858cd57c78858d1008802aa200302010055797eaa7e01877ec101587f77587981009c6301005c79009e63015177685b79009c6300cd53798800d10088760251207e5b797e01207e5a797e52797e7b757c67c0c859c88859c9009d00cd016a8800d100885acd5979885ad1c0c8885ad3009d5ad20100885bd10088c45c9d760200207e5b797e01207ec0c87e52797e7b757c6875675b79009c635a79009c6300cd52798800d10088030051205a797e01207e59797e787e7767c0c859c88859c9009d53795579950400e1f50596547978935479789455795279a06900cd02a91401205e797e5c797ea97e01877e8800d1c0c88800d3789d00d2008859cd55798859d1c0c88859d352799d59d2008858c7827758c77853947f77527f758158c7527953945279947f77787f7576827700a0766378517f75016a87776876635acd527988675acd016a88685ad100885bd10088c45c9d035100200111797e01207e60797e58797e587a757c6b7c6b7c6b7c6b7c6b7c6b7c6c6c6c6c6c6c6d6d6d7568675a79009c6300cd52798800d10088035151205a797e01207e59797e787e7767c0c859c88859c9009d00cd016a8800d100885acd5279885ad1c0c8885ad3009d5ad201ff885bd10088c45c9d03510020c0c87e01207e59797e787e7768686802aa20c101147f7552797eaa7e01877ec0cd886d67c0c859c88859c95a9d55ca827755ca7853947f77527f758155ca527953945279947f77787f7502a91401205b797e59797ea97e01877e00cd02aa20c101147f7501177e53797e54797eaa7e01877e8800d1008800ca827700ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686800ca537953945379945279947f7702aa20030200005d797e52797eaa7e01877e51cd8851d1008852ca827752ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686852ca537953945379945279947f7702aa20030200000111797e707c0114937f757e01207e01157901ff7eaa7e707c0135937f777eaa7e01877e52cd8852d1008853ca827753ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686853ca537953945379945279947f7702aa20030200000115797e52797eaa7e01877e53cd8853d1008854ca827754ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686854ca537953945379945279947f7702aa20030200000119797e52797eaa7e01877e54cd8854d1008857c7827757c77853947f77527f75815178529302ff00a063755367785293014ba0637552686857c7537953945379945279947f7755cd03020000011d797e52797e8855d1008802aa2003020000011d797eaa7e01877e56cd8856cc58c6a26956d158ce8856d3011a799d56d2008856ca827756ca7853947f77527f758156ca527953945279947f77787f7557cd02aa20c101147f7501207e01247901007eaa7e53797eaa7e01877e8857cc59c6a26957d159ce8857d359d09d57d259cf8802aa20525752807e0120797eaa7e01877e58cd8858d158ce8858d358d0011e79949d58d200886d6d6d6d6d6d6d6d6d6d6d6d6d75686d6d6d6d6d51").unwrap()); static IDO_PREINIT_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("c0519dc0c800c88800c9529dc0c852c88852c9539dc0c853c88853c9549dc0c854c88854c9559dc0c855c88855c9569dc0c856c88856c9579d5c79009e63c0c858c88858c9599d67c0c858c88858c9599d68c0c857c88857c9589d597981009c5d79009c9b5b7981009c9b63c0d1008852cd00c78852d1008853cd52c78853d1008854cd53c78854d1008855cd54c78855d1008856cd55c78856d1008857cd56c78857d100885c79009e6359cd58c78859cc58c6a26959d158ce8859d358d09d59d258cf8867597981009e5c79009e9a6459cd58c78859d10088686858cd57c78858d1008802aa200302010055797eaa7e01877ec101587f775b7981009c6301005f79009e63015177685e79009c6300cd53798800d10088760251207e5e797e01207e5d797e52797e7b757c67c0c859c88859c9009d00cd016a8800d100885acd5c79885ad1c0c8885ad3009d5ad20100885bd10088c45c9d760200207e5e797e01207ec0c87e52797e7b757c6875675e79009c635d79009c6300cd52798800d10088030051205d797e01207e5c797e787e7767c0c859c88859c9009d53795579950400e1f50596547978935479789455795279a06902aa20012060797e5d797e5c797eaa7e01877e5c798277009c6302a91401200111797e5c797ea97e01877e776800cd788800d1c0c88800d352799d00d2008859cd56798859d1c0c88859d353799d59d2008858c7827758c77853947f77527f758158c7527953945279947f77787f7576827700a06376517f75768176014b9f788b547982779f9a635279788b7f77537a757c6b7c6c5279517f757b757c6878016a8764016a537a757c6b7c6c686d67016a77685acd78885ad100885bd10088c45c9d035100200114797e01207e0113797e58797e587a757c6b7c6b7c6b7c6b7c6b7c6b7c6c6c6c6c6c6c6d6d6d7568675d79009c6300cd52798800d10088035151205d797e01207e5c797e787e7767c0c859c88859c9009d00cd016a8800d100885acd5279885ad1c0c8885ad3009d5ad201ff885bd10088c45c9d03510020c0c87e01207e5c797e787e7768686802aa20c101147f7552797eaa7e01877ec0cd886d67c0c859c88859c95a9d55ca827755ca7853947f77527f758155ca527953945279947f77787f75012302aa2001205f797e5d797e5b797eaa7e01877e7e5b798277009c63011702a914012060797e5b797ea97e01877e7e776800cd02aa20c101147f7553797e54797eaa7e01877e8800d1008800ca827700ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686800ca537953945379945279947f7702aa20030200005d797e52797eaa7e01877e51cd8851d1008852ca827752ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686852ca537953945379945279947f7702aa20030200000111797e707c0114937f757e01207e01187901ff7eaa7e707c0135937f777eaa7e01877e52cd8852d1008853ca827753ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686853ca537953945379945279947f7702aa20030200000115797e52797eaa7e01877e53cd8853d1008854ca827754ca7853947f77527f75815178529302ff00a063755367785293014ba0637552686854ca537953945379945279947f7702aa20030200000119797e52797eaa7e01877e54cd8854d1008857c7827757c77853947f77527f75815178529302ff00a063755367785293014ba0637552686857c7537953945379945279947f7755cd03020000011d797e52797e8855d1008802aa2003020000011d797eaa7e01877e56cd8856cc58c6a26956d158ce8856d3011a799d56d2008856ca827756ca7853947f77527f758156ca527953945279947f77787f7557cd02aa20c101147f7501207e01277901007eaa7e53797eaa7e01877e8857cc59c6a26957d159ce8857d359d09d57d259cf8802aa20525752807e0120797eaa7e01877e58cd8858d158ce8858d358d0011e79949d58d200886d6d6d6d6d6d6d6d6d6d6d6d6d75686d6d6d6d6d6d7551").unwrap());
static STORAGE_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("8178c99dc8c0c887").unwrap()); static STORAGE_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("8178c99dc8c0c887").unwrap());
static P2NFTH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("78ce7bcf7eaa87").unwrap()); static P2NFTH_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("78ce7bcf7eaa87").unwrap());
static CASHTOKENS_STUDIO_PAY2CATEGORY_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("51ce8851d0009d6300cdc0c7886851").unwrap()); static CASHTOKENS_STUDIO_PAY2CATEGORY_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("51ce8851d0009d6300cdc0c7886851").unwrap());
static REBUILD_IPFS_PLACEHOLDER_BCMR_FOR_GENESIS_WITH_AUTHGUARD_CONTRACT: LazyLock<Vec<u8>> = LazyLock::new(|| hex::decode("0902a9147ca97e01877e57897c6b00c08851d100887c635ab2756d51cd016a88674d0301404142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f6b007c8253a26365537f7c76011299527f77816c766b7c7f77517f75785c99527f77013f84816c766b7c7f77517f757e785699527f77013f84816c766b7c7f77517f757e7c527f77013f84816c766b7c7f77517f757e7b7c7e7c82539f666882760087636d677d537c94007c807e76011299527f77816c766b7c7f77517f75785c99527f77013f84816c766b7c7f77517f757e785699527f77013f84816c766b7c7f77517f757e7c527f77013f84816c766b7c7f77517f757e7c51937f757e686c7554893a10303132333435363738396162636465667c006b65517f7c5279785f84817f77517f756c7e6b52797c5499817f77517f756c7e6b82009c666d6c5689097f7b827b7c7f777e7e538978a8886b518ac0ce568a65766c537a538a6b74519c66756c766ba804015512207c7e548a01757c7e6b528a6c7c6b65766c537a538a6b74519c66756c6ca87c7e076a0442434d52207c7e51cd886801206c0f51ce8851d0009d6300cdc0c78868517e7e578a00cd8800ce00d18800d2008800d000d38800c600cca26952d10088c45387").unwrap());
#[serde_as]
#[derive(Serialize, Deserialize, Clone)]
pub struct IpfsBcmrWithPlaceholderMetadata {
#[serde_as(as = "serde_with::hex::Hex")]
registryReplaceCalls: Vec<u8>,
#[serde_as(as = "serde_with::hex::Hex")]
bcmrUrisReplaceCalls: Vec<u8>,
}
#[serde_as]
#[derive(Serialize, Deserialize, Clone)]
pub struct IpfsBcmrWithPlaceholder {
metadata: IpfsBcmrWithPlaceholderMetadata,
#[serde_as(as = "serde_with::hex::Hex")]
contentHash: Vec<u8>,
#[serde_as(as = "serde_with::hex::Hex")]
urisBytecode: Vec<u8>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct IdoPreInitBcmrParameters {
oToken: Option<IpfsBcmrWithPlaceholder>,
offering: Option<IpfsBcmrWithPlaceholder>,
}
pub struct IdoPreInitLockParameters { pub struct IdoPreInitLockParameters {
preInitBcmr: IdoPreInitBcmrParameters,
authguardLockingBytecode: Vec<u8>, authguardLockingBytecode: Vec<u8>,
permanentLiquidityShareNumerator: BigInt, permanentLiquidityShareNumerator: BigInt,
offeredTokenAmount: BigInt, offeredTokenAmount: BigInt,
@ -132,6 +164,7 @@ pub struct IdoParametersOffering {
#[serde_as] #[serde_as]
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub struct IdoPreInitParameters { pub struct IdoPreInitParameters {
preInitBcmr: IdoPreInitBcmrParameters,
#[serde_as(as = "serde_with::hex::Hex")] #[serde_as(as = "serde_with::hex::Hex")]
authguardLockingBytecode: Vec<u8>, authguardLockingBytecode: Vec<u8>,
authguardNftOutputIndex: BigInt, authguardNftOutputIndex: BigInt,
@ -144,6 +177,7 @@ pub struct IdoPreInitParameters {
#[serde_as] #[serde_as]
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub struct IdoActiveParameters { pub struct IdoActiveParameters {
preInitBcmr: IdoPreInitBcmrParameters,
#[serde_as(as = "serde_with::hex::Hex")] #[serde_as(as = "serde_with::hex::Hex")]
collectorNFTH: Vec<u8>, collectorNFTH: Vec<u8>,
permanentLiquidityShareNumerator: BigInt, permanentLiquidityShareNumerator: BigInt,
@ -261,23 +295,26 @@ fn build_storage_script_with_data(governingOutpointIndex: u32, data: &[u8]) -> S
Script::from(bytes) Script::from(bytes)
} }
fn extract_data_from_unlocking_bytecode_of_storage_with_data_with_size(unlocking_bytecode: Script) -> Result<Vec<u8>> { fn extract_data_from_storage_script_with_data_and_size(script: &Script) -> Result<Vec<u8>> {
let inst_list: Vec<_> = script.instructions().collect();
let n = inst_list.len();
if n < 2 {
return Err(anyhow::anyhow!("storage with data should have at least two instructions"));
}
match &inst_list[n - 2] {
Ok(Instruction::PushBytes(data)) => Ok(data[0..data.len()-2].to_vec()),
_ => Err(anyhow::anyhow!("storage with data should have a push opcode at instructions[count - 2]")),
}
}
fn extract_data_from_unlocking_bytecode_of_storage_with_data_and_size(unlocking_bytecode: &Script) -> Result<Vec<u8>> {
let instructions: Vec<_> = unlocking_bytecode.instructions().collect(); let instructions: Vec<_> = unlocking_bytecode.instructions().collect();
if instructions.len() != 2 { if instructions.len() != 2 {
return Err(anyhow::anyhow!("not a storage unlocking bytecode, should have only two push opcodes")); return Err(anyhow::anyhow!("not a storage unlocking bytecode, should have only two push opcodes"));
} }
match &instructions[1] { match &instructions[1] {
Ok(Instruction::PushBytes(redeem_bytecode)) => { Ok(Instruction::PushBytes(redeem_bytecode)) => {
let inner_script = Script::from(redeem_bytecode.to_vec()); extract_data_from_storage_script_with_data_and_size(&Script::from(redeem_bytecode.to_vec()))
let redeem_inst_list: Vec<_> = inner_script.instructions().collect();
let n = redeem_inst_list.len();
if n < 2 {
return Err(anyhow::anyhow!("storage with data should have at least two instructions"));
}
match &redeem_inst_list[n - 2] {
Ok(Instruction::PushBytes(data)) => Ok(data[0..data.len()-2].to_vec()),
_ => Err(anyhow::anyhow!("storage with data should have a push opcode at instructions[count - 2]")),
}
}, },
_ => Err(anyhow::anyhow!("invalid unlocking bytecode, p2sh redeem script push opcode is expected")), _ => Err(anyhow::anyhow!("invalid unlocking bytecode, p2sh redeem script push opcode is expected")),
} }
@ -374,13 +411,43 @@ fn build_partial_ido_initiator_bytecode(postLaunchPartialBytecode: &[u8], perman
bytecode bytecode
} }
fn create_rebuild_ipfs_placeholder_bcmr_partial_inputs(data: &IpfsBcmrWithPlaceholder) -> Vec<u8> {
let mut bcmrUrisWithReplaceCalls = Vec::new();
bcmrUrisWithReplaceCalls.extend_from_slice(&data.metadata.bcmrUrisReplaceCalls);
bcmrUrisWithReplaceCalls.extend_from_slice(&data.urisBytecode);
Builder::new()
.push_slice(&data.contentHash)
.push_slice(&data.metadata.registryReplaceCalls)
.push_int(1i64)
// OP_DEFINE
.push_opcode(bitcoincash::blockdata::opcodes::All::from(0x89u8))
.push_slice(&bcmrUrisWithReplaceCalls)
.push_int(2i64)
// OP_DEFINE
.push_opcode(bitcoincash::blockdata::opcodes::All::from(0x89u8))
.into_script()
.to_bytes()
}
fn build_preinit_bytecode(parameters: &IdoPreInitLockParameters, state: &IdoPreInitState) -> Vec<u8> { fn build_preinit_bytecode(parameters: &IdoPreInitLockParameters, state: &IdoPreInitState) -> Vec<u8> {
let rev_ido: Vec<u8> = state.idoCategory.iter().copied().rev().collect(); let rev_ido: Vec<u8> = state.idoCategory.iter().copied().rev().collect();
let rev_authguard: Vec<u8> = state.authguardCategory.iter().copied().rev().collect(); let rev_authguard: Vec<u8> = state.authguardCategory.iter().copied().rev().collect();
let offering_bcmr_partial_inputs = match &parameters.preInitBcmr.offering {
Some(bcmr) => create_rebuild_ipfs_placeholder_bcmr_partial_inputs(bcmr),
_ => Vec::new(),
};
let oToken_bcmr_partial_inputs = match &parameters.preInitBcmr.offering {
Some(bcmr) => create_rebuild_ipfs_placeholder_bcmr_partial_inputs(bcmr),
_ => Vec::new(),
};
let middle = Builder::new() let middle = Builder::new()
.push_slice(&rev_ido) .push_slice(&rev_ido)
.push_slice(&rev_authguard) .push_slice(&rev_authguard)
.push_slice(&parameters.authguardLockingBytecode) .push_slice(&parameters.authguardLockingBytecode)
.push_slice(&offering_bcmr_partial_inputs)
.push_slice(&oToken_bcmr_partial_inputs)
.push_slice(&REBUILD_IPFS_PLACEHOLDER_BCMR_FOR_GENESIS_WITH_AUTHGUARD_CONTRACT)
.push_slice(&CASHTOKENS_STUDIO_PAY2CATEGORY_CONTRACT) .push_slice(&CASHTOKENS_STUDIO_PAY2CATEGORY_CONTRACT)
.push_slice(&STORAGE_CONTRACT) .push_slice(&STORAGE_CONTRACT)
.into_script() .into_script()
@ -798,6 +865,51 @@ fn is_preinit_broadcast(
} }
} }
fn parse_ipfs_bcmr_with_placeholder(
bcmr_data: &[u8],
) -> Result<Option<IpfsBcmrWithPlaceholder>> {
if bcmr_data.len() == 0 ||
(bcmr_data[0] == 0 && bcmr_data.len() == 1) {
return Ok(None);
}
if bcmr_data.len() == 0 ||
!(bcmr_data[0] > 0 && bcmr_data[0] < 75) ||
bcmr_data[0].to_usize().unwrap() <= bcmr_data.len() {
return Err(anyhow::anyhow!("bcmr needs metadata!"));
}
let metadata_size = bcmr_data[0].to_usize().unwrap();
let metadata_script = Script::from(bcmr_data[0..metadata_size].to_vec());
let metadata_inst_list: Vec<_> = metadata_script.instructions().collect();
if metadata_inst_list.len() != 2 {
return Err(anyhow::anyhow!("bcmr metadata should have two push opcodes!"));
}
let registryReplaceCalls = match &metadata_inst_list[0] {
Ok(Instruction::PushBytes(data)) => data.to_vec(),
_ => {
return Err(anyhow::anyhow!("oToken bcmr metadata opcode#0 is not a push opcode"));
}
};
let bcmrUrisReplaceCalls = match &metadata_inst_list[0] {
Ok(Instruction::PushBytes(data)) => data.to_vec(),
_ => {
return Err(anyhow::anyhow!("oToken bcmr metadata opcode#0 is not a push opcode"));
}
};
let bcmr_opreturn: Vec<_> = bcmr_data[metadata_size..bcmr_data.len()].to_vec();
if bcmr_opreturn.len() < BCMR_SIGNATURE.len() + 32 ||
&bcmr_opreturn[0..BCMR_SIGNATURE.len()] != BCMR_SIGNATURE {
return Err(anyhow::anyhow!("invalid bcmr opreturn"));
}
Ok(Some(IpfsBcmrWithPlaceholder {
metadata: IpfsBcmrWithPlaceholderMetadata {
registryReplaceCalls,
bcmrUrisReplaceCalls,
},
contentHash: bcmr_opreturn[BCMR_SIGNATURE.len()..BCMR_SIGNATURE.len()+32].to_vec(),
urisBytecode: bcmr_opreturn[BCMR_SIGNATURE.len()+32..bcmr_opreturn.len()].to_vec(),
}))
}
struct IdoContext { struct IdoContext {
preinit_txid: Vec<u8>, preinit_txid: Vec<u8>,
init_txid: Option<Vec<u8>>, init_txid: Option<Vec<u8>>,
@ -817,7 +929,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
Some(Network::Bitcoin) => MAINNET_PLATFORM_FEE_NFTH.clone(), Some(Network::Bitcoin) => MAINNET_PLATFORM_FEE_NFTH.clone(),
_ => MAINNET_PLATFORM_FEE_NFTH.clone(), _ => MAINNET_PLATFORM_FEE_NFTH.clone(),
}; };
let mut offered_token_is_in_supply = false; let offered_token_is_in_supply;
let mut is_valid_ido = true; let mut is_valid_ido = true;
// verify the ido is created correctly // verify the ido is created correctly
let preinit_parameters: IdoPreInitParameters; let preinit_parameters: IdoPreInitParameters;
@ -844,7 +956,38 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
if data.len() < 185 { if data.len() < 185 {
return Err(anyhow::anyhow!("Incorrect announcement.mainData size")); return Err(anyhow::anyhow!("Incorrect announcement.mainData size"));
} }
// preinit_parameters.offeredTokenTotalSupply < BigInt::from(0)
offered_token_is_in_supply = vm_number_to_bigint(&data[168..176]) < BigInt::from(0);
let offeringBcmrStorageOut = tx.output.get(8);
if offeringBcmrStorageOut.is_none() {
return Err(anyhow::anyhow!("offering bcmr storage not defined!"));
}
let offeringBcmr = parse_ipfs_bcmr_with_placeholder(
&extract_data_from_storage_script_with_data_and_size(
&offeringBcmrStorageOut.unwrap().script_pubkey
)?
)?;
let mut oTokenBcmr: Option<IpfsBcmrWithPlaceholder> = None;
if offered_token_is_in_supply {
let oTokenBcmrStorageOut = tx.output.get(9);
if oTokenBcmrStorageOut.is_none() {
return Err(anyhow::anyhow!("oToken bcmr storage not defined!"));
}
oTokenBcmr = parse_ipfs_bcmr_with_placeholder(
&extract_data_from_storage_script_with_data_and_size(
&oTokenBcmrStorageOut.unwrap().script_pubkey
)?
)?;
}
preinit_parameters = IdoPreInitParameters { preinit_parameters = IdoPreInitParameters {
preInitBcmr: IdoPreInitBcmrParameters {
offering: offeringBcmr,
oToken: oTokenBcmr,
},
authguardLockingBytecode: authguardLockingBytecode, authguardLockingBytecode: authguardLockingBytecode,
offering: IdoParametersOffering { offering: IdoParametersOffering {
platformFeeNFTH: data[10..42].to_vec(), platformFeeNFTH: data[10..42].to_vec(),
@ -878,9 +1021,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
if preinit_parameters.offering.offer.xTokenCategory.is_some() { if preinit_parameters.offering.offer.xTokenCategory.is_some() {
return Err(anyhow::anyhow!("non-null xTokenCategory is not supported")); return Err(anyhow::anyhow!("non-null xTokenCategory is not supported"));
} }
if preinit_parameters.offeredTokenTotalSupply < BigInt::from(0) { if !offered_token_is_in_supply {
offered_token_is_in_supply = true;
} else {
let permanentLiquidityOTokenReserve: BigInt = &preinit_parameters.offeredTokenAmount * &preinit_parameters.permanentLiquidityShareNumerator / &PERMANENT_LIQUIDITY_SHARE_DENOMINATOR.clone(); let permanentLiquidityOTokenReserve: BigInt = &preinit_parameters.offeredTokenAmount * &preinit_parameters.permanentLiquidityShareNumerator / &PERMANENT_LIQUIDITY_SHARE_DENOMINATOR.clone();
if preinit_parameters.offeredTokenTotalSupply <= &preinit_parameters.offeredTokenAmount + &permanentLiquidityOTokenReserve { if preinit_parameters.offeredTokenTotalSupply <= &preinit_parameters.offeredTokenAmount + &permanentLiquidityOTokenReserve {
info!("ido parse, not a valid ido, preinit_parameters.offeredTokenTotalSupply <= preinit_parameters.offeredTokenAmount + permanentLiquidityOTokenReserve"); info!("ido parse, not a valid ido, preinit_parameters.offeredTokenTotalSupply <= preinit_parameters.offeredTokenAmount + permanentLiquidityOTokenReserve");
@ -922,6 +1063,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
} }
let preInit_lock_parameters = IdoPreInitLockParameters { let preInit_lock_parameters = IdoPreInitLockParameters {
preInitBcmr: preinit_parameters.preInitBcmr.clone(),
authguardLockingBytecode: preinit_parameters.authguardLockingBytecode.clone(), authguardLockingBytecode: preinit_parameters.authguardLockingBytecode.clone(),
permanentLiquidityShareNumerator: preinit_parameters.permanentLiquidityShareNumerator.clone(), permanentLiquidityShareNumerator: preinit_parameters.permanentLiquidityShareNumerator.clone(),
offeredTokenAmount: preinit_parameters.offeredTokenAmount.clone(), offeredTokenAmount: preinit_parameters.offeredTokenAmount.clone(),
@ -1257,8 +1399,10 @@ fn ido_add_tx(
// init outputs created & init tx // init outputs created & init tx
updates.push(IdoUpdate::Status("ACTIVE".to_string())); updates.push(IdoUpdate::Status("ACTIVE".to_string()));
updates.push(IdoUpdate::InitTxId(tx.txid().to_blob())); updates.push(IdoUpdate::InitTxId(tx.txid().to_blob()));
let launcherBytecodeIn = tx.input.get(2).ok_or_else(|| anyhow::anyhow!("launcher bytecode storage does not exist!"))?; let launcherBytecodeIn = tx.input.get(2)
let launcher_data = extract_data_from_unlocking_bytecode_of_storage_with_data_with_size(launcherBytecodeIn.script_sig.clone()).map_err(|e| anyhow::anyhow!("failed to extract launcher bytecode: {e}"))?; .ok_or_else(|| anyhow::anyhow!("launcher bytecode storage does not exist!"))?;
let launcher_data = extract_data_from_unlocking_bytecode_of_storage_with_data_and_size(&launcherBytecodeIn.script_sig)
.map_err(|e| anyhow::anyhow!("failed to extract launcher bytecode: {e}"))?;
let launcher_script = Script::from(launcher_data); let launcher_script = Script::from(launcher_data);
let launcher_inst_list: Vec<_> = launcher_script.instructions().collect(); let launcher_inst_list: Vec<_> = launcher_script.instructions().collect();
let collectorNFTH: Vec<u8>; let collectorNFTH: Vec<u8>;
@ -1279,6 +1423,7 @@ fn ido_add_tx(
_ => return Err(anyhow::anyhow!("expecting PreInit parameters")), _ => return Err(anyhow::anyhow!("expecting PreInit parameters")),
} }
updates.push(IdoUpdate::Parameters(IdoParameters::Active(IdoActiveParameters { updates.push(IdoUpdate::Parameters(IdoParameters::Active(IdoActiveParameters {
preInitBcmr: preinit_params.preInitBcmr.clone(),
collectorNFTH: collectorNFTH, collectorNFTH: collectorNFTH,
permanentLiquidityShareNumerator: preinit_params.permanentLiquidityShareNumerator.clone(), permanentLiquidityShareNumerator: preinit_params.permanentLiquidityShareNumerator.clone(),
offeredTokenAmount: preinit_params.offeredTokenAmount.clone(), offeredTokenAmount: preinit_params.offeredTokenAmount.clone(),
@ -1421,10 +1566,10 @@ fn ido_add_tx(
"DISTRIBUTING" => { "DISTRIBUTING" => {
match &context.parameters { match &context.parameters {
IdoParameters::Active(parameters) => { IdoParameters::Active(parameters) => {
// enforce limitation (xToken == NATIVE_BCH) // enforce limitation (xToken == NATIVE_BCH)
if parameters.offering.offer.xTokenCategory.is_some() { if parameters.offering.offer.xTokenCategory.is_some() {
return Err(anyhow::anyhow!("non-null xTokenCategory is not supported")); return Err(anyhow::anyhow!("non-null xTokenCategory is not supported"));
} }
} }
_ => return Err(anyhow::anyhow!("expecting active parameters")), _ => return Err(anyhow::anyhow!("expecting active parameters")),
} }