make governance work over exodus
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
2387a2fe32
commit
f2544e3876
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-exodus"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
description = "Threshold signature generation with DKG included"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
@ -472,6 +472,7 @@ mod benchmarks {
|
||||
|
||||
#[benchmark]
|
||||
fn register_nonce_commitment() -> Result<(), BenchmarkError> {
|
||||
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
||||
let (mut dkg_state, network_curve, authority, authority_index) =
|
||||
prepare_pallet::<T>(1);
|
||||
|
||||
@ -483,9 +484,22 @@ mod benchmarks {
|
||||
dkg_state.insert_index(authority_index);
|
||||
let exodus_session = CurrentExodus::<T>::get();
|
||||
|
||||
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
||||
let dummy_address = EvmAddress::repeat_byte(69);
|
||||
let dummy_nonce = vec![0u8; network_curve.element_bytes_len()];
|
||||
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
|
||||
|
||||
let create_bond = GovernanceAction::Create {
|
||||
market: [69, 420, 1337],
|
||||
terms: [420, 1337],
|
||||
token: dummy_address,
|
||||
intervals: [34, 35],
|
||||
booleans: [true, true],
|
||||
};
|
||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
||||
exodus_session,
|
||||
network_id,
|
||||
dummy_address,
|
||||
create_bond,
|
||||
);
|
||||
|
||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
||||
@ -534,6 +548,7 @@ mod benchmarks {
|
||||
|
||||
#[benchmark]
|
||||
fn register_group_commitment() -> Result<(), BenchmarkError> {
|
||||
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
||||
let (mut dkg_state, network_curve, authority, authority_index) =
|
||||
prepare_pallet::<T>(1);
|
||||
|
||||
@ -546,9 +561,23 @@ mod benchmarks {
|
||||
let exodus_session = CurrentExodus::<T>::get();
|
||||
|
||||
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
||||
let dummy_address = EvmAddress::repeat_byte(69);
|
||||
let dummy_merkle_root = ExodusHash::repeat_byte(69);
|
||||
let dummy_group_commitment = vec![0u8; network_curve.element_bytes_len()];
|
||||
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
|
||||
|
||||
let create_bond = GovernanceAction::Create {
|
||||
market: [69, 420, 1337],
|
||||
terms: [420, 1337],
|
||||
token: dummy_address,
|
||||
intervals: [34, 35],
|
||||
booleans: [true, true],
|
||||
};
|
||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
||||
exodus_session,
|
||||
network_id,
|
||||
dummy_address,
|
||||
create_bond,
|
||||
);
|
||||
|
||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
||||
@ -609,6 +638,7 @@ mod benchmarks {
|
||||
fn register_signature_share() -> Result<(), BenchmarkError> {
|
||||
let max_signers = T::MaxAuthorities::get();
|
||||
let threshold = get_byzantium_threshold(max_signers);
|
||||
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
||||
|
||||
let (mut dkg_state, network_curve, authority, authority_index) =
|
||||
prepare_pallet::<T>(max_signers as usize);
|
||||
@ -632,8 +662,20 @@ mod benchmarks {
|
||||
];
|
||||
dummy_element[1..33].copy_from_slice(&g_x_coords);
|
||||
|
||||
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
||||
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
|
||||
let dummy_address = EvmAddress::repeat_byte(69);
|
||||
let create_bond = GovernanceAction::Create {
|
||||
market: [69, 420, 1337],
|
||||
terms: [420, 1337],
|
||||
token: dummy_address,
|
||||
intervals: [34, 35],
|
||||
booleans: [true, true],
|
||||
};
|
||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
||||
exodus_session,
|
||||
network_id,
|
||||
dummy_address,
|
||||
create_bond,
|
||||
);
|
||||
|
||||
let mut dummy_scalar = vec![0u8; network_curve.scalar_bytes_len()];
|
||||
dummy_scalar[network_curve.scalar_bytes_len() - 1] = 1;
|
||||
@ -755,7 +797,7 @@ mod benchmarks {
|
||||
assert!(!committers_exists);
|
||||
|
||||
assert!(!ExodusRequests::<T>::contains_key(&network_curve, &exodus_session));
|
||||
assert!(ExodusSignedRotations::<T>::contains_key((&exodus_session, NetworkType::Evm), dkg_index));
|
||||
assert!(ExodusSignedGovernance::<T>::contains_key((&exodus_session, network_id), dkg_index));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ const EXODUS_PREFIX_SHARES: &[u8] = b"exodus-shares";
|
||||
const EXODUS_PREFIX_BLENDS: &[u8] = b"exodus-blends";
|
||||
const EXODUS_PREFIX_EXILES: &[u8] = b"exodus-exiles";
|
||||
|
||||
const MAX_MESSAGE_SIZE : u32 = 420;
|
||||
const MAX_MESSAGE_SIZE : u32 = 512;
|
||||
const HEADER_MAX_BYTES : u32 = 1 + 4;
|
||||
const ELEMENT_MAX_BYTES : u32 = 33;
|
||||
const SCALAR_MAX_BYTES : u32 = 32;
|
||||
|
||||
@ -1132,8 +1132,13 @@ fn test_all_validators_can_execute_dkg() {
|
||||
ExodusSignedBridges::<Runtime>::iter().count()
|
||||
});
|
||||
|
||||
let governances_count = ext.execute_with(|| {
|
||||
ExodusSignedGovernance::<Runtime>::iter().count()
|
||||
});
|
||||
|
||||
assert_eq!(rotations_count, 3);
|
||||
assert_eq!(bridges_count, 2);
|
||||
assert_eq!(governances_count, 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -71,10 +71,70 @@ macro_rules! impl_evm_encodable {
|
||||
}
|
||||
)*
|
||||
};
|
||||
|
||||
(const_array: $( [ $inner_ty:ty ; $len:expr ] ),* $(,)? ) => {
|
||||
$(
|
||||
impl EvmAbiEncode for [ $inner_ty ; $len ] {
|
||||
#[inline(always)]
|
||||
fn size(&self) -> usize {
|
||||
$len * 32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn abi_encode(&self, buffer: &mut [u8], cursor: &mut usize) -> Option<()> {
|
||||
for item in self.iter() {
|
||||
EvmAbiEncode::abi_encode(item, buffer, cursor)?;
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
|
||||
(bytes_slice: ) => {
|
||||
impl EvmAbiEncode for [u8] {
|
||||
#[inline(always)]
|
||||
fn size(&self) -> usize {
|
||||
let content_len = self.len();
|
||||
let remainder = content_len % 32;
|
||||
let alignment = if remainder == 0 { 0 } else { 32 - remainder };
|
||||
32 + content_len + alignment
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn abi_encode(&self, buffer: &mut [u8], cursor: &mut usize) -> Option<()> {
|
||||
if self.size() >= MAX_MESSAGE_SIZE as usize { return None; }
|
||||
|
||||
let pointer = cursor.checked_sub(4).map(|x| x.saturating_add(32))?;
|
||||
let head_pointer = pointer as u32;
|
||||
EvmAbiEncode::abi_encode(&head_pointer, buffer, cursor);
|
||||
|
||||
let content_len = self.len() as u32;
|
||||
|
||||
EvmAbiEncode::abi_encode(&content_len, buffer, cursor)?;
|
||||
|
||||
let value_slice = buffer.get_mut(*cursor..*cursor + self.len())?;
|
||||
value_slice.copy_from_slice(self);
|
||||
*cursor += self.len();
|
||||
|
||||
let remainder = self.len() % 32;
|
||||
if remainder != 0 {
|
||||
let alignment = 32 - remainder;
|
||||
let alignment_slice = buffer.get_mut(*cursor..*cursor + alignment)?;
|
||||
alignment_slice.fill(0);
|
||||
*cursor += alignment;
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_evm_encodable!(numeric: u8, u16, u32, u64, u128);
|
||||
impl_evm_encodable!(bytes_fixed: EvmAddress, EvmBytes32);
|
||||
impl_evm_encodable!(const_array: [u128; 3], [u128; 2], [u32; 2], [u8; 2]);
|
||||
impl_evm_encodable!(bytes_slice:);
|
||||
|
||||
macro_rules! abi_encode_evm_message {
|
||||
($buffer:expr, $sig:expr, [ $( $val:expr ),* $(,)? ]) => {{
|
||||
@ -102,6 +162,152 @@ macro_rules! abi_encode_evm_message {
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
|
||||
#[repr(u8)]
|
||||
pub enum GovernanceStatus {
|
||||
ReserveDepositor = 0,
|
||||
ReserveToken = 1,
|
||||
LiquidityDepositor = 2,
|
||||
LiquidityToken = 3,
|
||||
RewardManager = 4,
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
||||
pub enum GovernanceAction {
|
||||
SetDistributor { distributor: EvmAddress },
|
||||
SetWarmupPeriod { warmup_period: u128 },
|
||||
UpdateGatekeeperAddress { new_gatekeeper: EvmAddress },
|
||||
|
||||
SetBounty { bounty: u128 },
|
||||
AddPool { address: EvmAddress },
|
||||
RemovePool { index: u128 },
|
||||
SetAdjustment { rate: u128, target: u128, add: bool },
|
||||
|
||||
Enable { status: GovernanceStatus, address: EvmAddress, calculator: EvmAddress },
|
||||
Disable { status: GovernanceStatus, address: EvmAddress },
|
||||
ForfeitReserves { router: EvmAddress, liquidity: u128, destroyer_mode: bool },
|
||||
RedeemReserves { router: EvmAddress, amount: u128 },
|
||||
Withdraw { token: EvmAddress, amount: u128 },
|
||||
AuditReserves,
|
||||
|
||||
Close { id: u128 },
|
||||
Create {
|
||||
market: [u128; 3],
|
||||
terms: [u128; 2],
|
||||
token: EvmAddress,
|
||||
intervals: [u32; 2],
|
||||
booleans: [bool; 2],
|
||||
},
|
||||
}
|
||||
|
||||
impl GovernanceAction {
|
||||
pub fn get_message<'a>(
|
||||
&self,
|
||||
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
|
||||
) -> Option<&'a [u8]> {
|
||||
match &self {
|
||||
Self::SetDistributor { distributor } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"setDistributor(address)",
|
||||
[distributor]
|
||||
)
|
||||
},
|
||||
Self::SetWarmupPeriod { warmup_period } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"setWarmupPeriod(uint256)",
|
||||
[warmup_period]
|
||||
)
|
||||
},
|
||||
Self::UpdateGatekeeperAddress { new_gatekeeper } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"updateGatekeeperAddress(address)",
|
||||
[new_gatekeeper]
|
||||
)
|
||||
},
|
||||
Self::SetBounty { bounty } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"setBounty(uint256)",
|
||||
[bounty]
|
||||
)
|
||||
},
|
||||
Self::AddPool { address } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"addPool(address)",
|
||||
[address]
|
||||
)
|
||||
},
|
||||
Self::RemovePool { index } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"removePool(uint256)",
|
||||
[index]
|
||||
)
|
||||
},
|
||||
Self::SetAdjustment { rate, target, add } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"setAdjustment(uint256,uint256,bool)",
|
||||
[rate, target, &(*add as u8)]
|
||||
)
|
||||
},
|
||||
Self::Enable { status, address, calculator } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"enable(uint8,address,address)",
|
||||
[&(*status as u8), address, calculator]
|
||||
)
|
||||
},
|
||||
Self::Disable { status, address } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"disable(uint8,address)",
|
||||
[&(*status as u8), address]
|
||||
)
|
||||
},
|
||||
Self::ForfeitReserves { router, liquidity, destroyer_mode } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"forfeitReserves(address,uint256,bool)",
|
||||
[router, liquidity, &(*destroyer_mode as u8)]
|
||||
)
|
||||
},
|
||||
Self::RedeemReserves { router, amount } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"redeemReserve(address,uint256)",
|
||||
[router, amount]
|
||||
)
|
||||
},
|
||||
Self::Withdraw { token, amount } => {
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"withdraw(address,uint256)",
|
||||
[token, amount]
|
||||
)
|
||||
},
|
||||
Self::AuditReserves => {
|
||||
abi_encode_evm_message!(message_buffer, "auditReserves()", [])
|
||||
},
|
||||
Self::Close { id } => {
|
||||
abi_encode_evm_message!(message_buffer, "close(uint256)", [id])
|
||||
},
|
||||
Self::Create { market, terms, token, intervals, booleans } => {
|
||||
let booleans_u8 = [booleans[0] as u8, booleans[1] as u8];
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"create(uint256[3],uint256[2],address,uint32[2],bool[2])",
|
||||
[market, terms, token, intervals, &booleans_u8]
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
||||
pub struct ExodusRequest<NetworkId, Balance> {
|
||||
pub r#type: ExodusRequestType<NetworkId, Balance>,
|
||||
@ -123,7 +329,12 @@ pub enum ExodusRequestType<NetworkId, Balance> {
|
||||
bounty: Perbill,
|
||||
receiver: EvmAddress,
|
||||
},
|
||||
EvmGovernance { network_id: NetworkId },
|
||||
EvmGovernance {
|
||||
exodus_session: ExodusSession,
|
||||
network_id: NetworkId,
|
||||
target: EvmAddress,
|
||||
action: GovernanceAction,
|
||||
},
|
||||
UtxoBridgeOut { network_id: NetworkId },
|
||||
}
|
||||
|
||||
@ -144,6 +355,24 @@ where
|
||||
[exodus_session, public_key, parity]
|
||||
)
|
||||
},
|
||||
ExodusRequestType::EvmGovernance { exodus_session, network_id, target, action } => {
|
||||
let mut action_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||
let action_payload = action.get_message(&mut action_buffer)?;
|
||||
|
||||
let mut metadata_buffer = [0u8; 32];
|
||||
|
||||
let chain_id_u64: u64 = (*network_id).unique_saturated_into();
|
||||
metadata_buffer[0..8].copy_from_slice(&chain_id_u64.to_be_bytes());
|
||||
metadata_buffer[8..28].copy_from_slice(target.as_ref());
|
||||
|
||||
let packed_metadata = EvmBytes32::from(&metadata_buffer);
|
||||
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"govern(uint256,uint256,bytes)",
|
||||
[exodus_session, &packed_metadata, action_payload]
|
||||
)
|
||||
},
|
||||
ExodusRequestType::EvmBridgeOut { exodus_session, network_id, amount, bounty, receiver } => {
|
||||
let mut buffer = [0u8; 32];
|
||||
buffer[0..20].copy_from_slice(receiver.as_ref());
|
||||
@ -170,7 +399,7 @@ where
|
||||
|
||||
abi_encode_evm_message!(
|
||||
message_buffer,
|
||||
"materialize(uint256,uint256,uint256)",
|
||||
"recall(uint256,uint256,uint256)",
|
||||
[exodus_session, &amount_u256, &packed_metadata]
|
||||
)
|
||||
}
|
||||
@ -221,6 +450,21 @@ where
|
||||
Self::default_request_for(evm_bridge_out)
|
||||
}
|
||||
|
||||
pub fn evm_governance(
|
||||
exodus_session: ExodusSession,
|
||||
network_id: NetworkId,
|
||||
target: EvmAddress,
|
||||
action: GovernanceAction,
|
||||
) -> Self {
|
||||
let evm_governance = ExodusRequestType::EvmGovernance {
|
||||
exodus_session,
|
||||
network_id,
|
||||
target,
|
||||
action,
|
||||
};
|
||||
Self::default_request_for(evm_governance)
|
||||
}
|
||||
|
||||
pub fn is_rotation(&self) -> bool {
|
||||
match &self.r#type {
|
||||
ExodusRequestType::EvmRotation { .. } | ExodusRequestType::UtxoRotation { .. } => true,
|
||||
@ -234,3 +478,255 @@ where
|
||||
Self { r#type: request_type, next_roast_session: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_io::hashing::keccak_256;
|
||||
|
||||
#[test]
|
||||
fn test_rotation_message_valid() {
|
||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||
let public_key = EvmBytes32::repeat_byte(0x11);
|
||||
let session = 69u64;
|
||||
|
||||
let rotation_request = ExodusRequest::<u64, u128>::evm_rotation(
|
||||
session,
|
||||
public_key.clone(),
|
||||
1,
|
||||
);
|
||||
|
||||
let calldata = rotation_request.get_message(&mut buffer).unwrap();
|
||||
assert_eq!(calldata.len(), 100);
|
||||
|
||||
let expected_hash = keccak_256("rotate(uint256,bytes32,uint8)".as_bytes());
|
||||
|
||||
assert_eq!(calldata[0..4], expected_hash[0..4]);
|
||||
assert_eq!(calldata[35], 0x45);
|
||||
assert_eq!(&calldata[4..35], &[0u8; 31]);
|
||||
assert_eq!(&calldata[36..68], public_key.as_ref());
|
||||
assert_eq!(calldata[99], 1);
|
||||
assert_eq!(&calldata[68..99], &[0u8; 31]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bridge_out_message_valid() {
|
||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||
let receiver = EvmAddress::repeat_byte(0xAA);
|
||||
let network_id = 420u64;
|
||||
let session = 69u64;
|
||||
|
||||
let bridge_request = ExodusRequest::<u64, u128>::evm_bridge_out(
|
||||
session,
|
||||
network_id,
|
||||
1_000_000u128,
|
||||
sp_runtime::Perbill::from_percent(1),
|
||||
receiver.clone()
|
||||
);
|
||||
|
||||
let calldata = bridge_request.get_message(&mut buffer).unwrap();
|
||||
assert_eq!(calldata.len(), 100);
|
||||
|
||||
let expected_hash = keccak_256("recall(uint256,uint256,uint256)".as_bytes());
|
||||
assert_eq!(calldata[0..4], expected_hash[0..4]);
|
||||
assert_eq!(calldata[35], 69);
|
||||
assert_eq!(calldata[67], 0x40);
|
||||
assert_eq!(calldata[66], 0x42);
|
||||
assert_eq!(calldata[65], 0x0F);
|
||||
|
||||
let metadata_slot = &calldata[68..100];
|
||||
assert_eq!(&metadata_slot[0..20], receiver.as_ref());
|
||||
assert_eq!(metadata_slot[27], 0xA4);
|
||||
assert_eq!(metadata_slot[26], 0x01);
|
||||
|
||||
assert_eq!(metadata_slot[31], 0x28);
|
||||
assert_eq!(metadata_slot[30], 0x5C);
|
||||
assert_eq!(metadata_slot[29], 0x8F);
|
||||
assert_eq!(metadata_slot[28], 0x02);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_governance_message_valid() {
|
||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||
let target = EvmAddress::repeat_byte(0xAA);
|
||||
let network_id = 420u64;
|
||||
let session = 69u64;
|
||||
|
||||
let actions = vec![
|
||||
GovernanceAction::SetDistributor { distributor: EvmAddress::repeat_byte(0x11) },
|
||||
GovernanceAction::SetWarmupPeriod { warmup_period: 3600 },
|
||||
GovernanceAction::UpdateGatekeeperAddress { new_gatekeeper: EvmAddress::repeat_byte(0x22) },
|
||||
|
||||
GovernanceAction::SetBounty { bounty: 500 },
|
||||
GovernanceAction::AddPool { address: EvmAddress::repeat_byte(0x22) },
|
||||
GovernanceAction::RemovePool { index: 2 },
|
||||
GovernanceAction::SetAdjustment { rate: 10, target: 100, add: true },
|
||||
|
||||
GovernanceAction::Enable {
|
||||
status: GovernanceStatus::ReserveDepositor,
|
||||
address: EvmAddress::repeat_byte(0x33),
|
||||
calculator: EvmAddress::repeat_byte(0x44)
|
||||
},
|
||||
GovernanceAction::Disable {
|
||||
status: GovernanceStatus::ReserveToken,
|
||||
address: EvmAddress::repeat_byte(0x55)
|
||||
},
|
||||
GovernanceAction::ForfeitReserves {
|
||||
router: EvmAddress::repeat_byte(0x66),
|
||||
liquidity: 5000,
|
||||
destroyer_mode: false
|
||||
},
|
||||
GovernanceAction::RedeemReserves { router: EvmAddress::repeat_byte(0x77), amount: 10000 },
|
||||
GovernanceAction::Withdraw { token: EvmAddress::repeat_byte(0x88), amount: 2500 },
|
||||
GovernanceAction::AuditReserves,
|
||||
|
||||
GovernanceAction::Close { id: 99 },
|
||||
GovernanceAction::Create {
|
||||
market: [69, 420, 1337],
|
||||
terms: [69, 420],
|
||||
token: EvmAddress::repeat_byte(0x99),
|
||||
intervals: [69, 1337],
|
||||
booleans: [true, false],
|
||||
},
|
||||
];
|
||||
|
||||
for (index, action) in actions.into_iter().enumerate() {
|
||||
let action_clone = action.clone();
|
||||
|
||||
let governance_request = ExodusRequest::<u64, u128>::evm_governance(
|
||||
session,
|
||||
network_id,
|
||||
target,
|
||||
action,
|
||||
);
|
||||
|
||||
let message = governance_request
|
||||
.get_message(&mut buffer)
|
||||
.get_or_insert(&[])
|
||||
.to_vec();
|
||||
|
||||
assert!(!message.is_empty(), "Failed to encode action at index {}", index);
|
||||
|
||||
let expected_master_hash = keccak_256("govern(uint256,uint256,bytes)".as_bytes());
|
||||
assert_eq!(message[0..4], expected_master_hash[0..4]);
|
||||
|
||||
assert_eq!(message[35], 69);
|
||||
assert_eq!(&message[4..35], &[0u8; 31]);
|
||||
|
||||
assert_eq!(message[43], 0xA4);
|
||||
assert_eq!(message[42], 0x01);
|
||||
assert_eq!(&message[44..64], target.as_ref());
|
||||
assert_eq!(&message[64..68], &[0u8; 4]);
|
||||
|
||||
assert_eq!(message[99], 96);
|
||||
|
||||
let inner_payload_len = u32::from_be_bytes(message[128..132].try_into().unwrap()) as usize;
|
||||
let inner_payload = &message[132..132 + inner_payload_len];
|
||||
|
||||
assert_eq!((message.len() - 4) % 32, 0);
|
||||
|
||||
match action_clone {
|
||||
GovernanceAction::SetDistributor { distributor } => {
|
||||
let hash = keccak_256("setDistributor(address)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], distributor.as_ref());
|
||||
},
|
||||
GovernanceAction::SetWarmupPeriod { warmup_period } => {
|
||||
let hash = keccak_256("setWarmupPeriod(uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[inner_payload.len() - 1], warmup_period as u8);
|
||||
},
|
||||
GovernanceAction::UpdateGatekeeperAddress { new_gatekeeper } => {
|
||||
let hash = keccak_256("updateGatekeeperAddress(address)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], new_gatekeeper.as_ref());
|
||||
},
|
||||
GovernanceAction::SetBounty { bounty } => {
|
||||
let hash = keccak_256("setBounty(uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[inner_payload.len() - 1], bounty as u8);
|
||||
},
|
||||
GovernanceAction::AddPool { address } => {
|
||||
let hash = keccak_256("addPool(address)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], address.as_ref());
|
||||
},
|
||||
GovernanceAction::RemovePool { index } => {
|
||||
let hash = keccak_256("removePool(uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[inner_payload.len() - 1], index as u8);
|
||||
},
|
||||
GovernanceAction::SetAdjustment { rate, target, add } => {
|
||||
let hash = keccak_256("setAdjustment(uint256,uint256,bool)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[35], rate as u8);
|
||||
assert_eq!(inner_payload[67], target as u8);
|
||||
assert_eq!(inner_payload[99], add as u8);
|
||||
},
|
||||
GovernanceAction::Enable { status, address, calculator } => {
|
||||
let hash = keccak_256("enable(uint8,address,address)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[35], status as u8);
|
||||
assert_eq!(&inner_payload[48..68], address.as_ref());
|
||||
assert_eq!(&inner_payload[80..100], calculator.as_ref());
|
||||
},
|
||||
GovernanceAction::Disable { status, address } => {
|
||||
let hash = keccak_256("disable(uint8,address)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[35], status as u8);
|
||||
assert_eq!(&inner_payload[48..68], address.as_ref());
|
||||
},
|
||||
GovernanceAction::ForfeitReserves { router, liquidity, destroyer_mode } => {
|
||||
let hash = keccak_256("forfeitReserves(address,uint256,bool)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], router.as_ref());
|
||||
assert_eq!(inner_payload[67], liquidity as u8);
|
||||
assert_eq!(inner_payload[99], destroyer_mode as u8);
|
||||
},
|
||||
GovernanceAction::RedeemReserves { router, amount } => {
|
||||
let hash = keccak_256("redeemReserve(address,uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], router.as_ref());
|
||||
assert_eq!(inner_payload[67], amount as u8);
|
||||
},
|
||||
GovernanceAction::Withdraw { token, amount } => {
|
||||
let hash = keccak_256("withdraw(address,uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(&inner_payload[16..36], token.as_ref());
|
||||
assert_eq!(inner_payload[67], amount as u8);
|
||||
},
|
||||
GovernanceAction::AuditReserves => {
|
||||
let hash = keccak_256("auditReserves()".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload.len(), 4);
|
||||
},
|
||||
GovernanceAction::Close { id } => {
|
||||
let hash = keccak_256("close(uint256)".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload[inner_payload.len() - 1], id as u8);
|
||||
},
|
||||
GovernanceAction::Create { market, terms, token, intervals, booleans } => {
|
||||
let hash = keccak_256("create(uint256[3],uint256[2],address,uint32[2],bool[2])".as_bytes());
|
||||
assert_eq!(inner_payload[0..4], hash[0..4]);
|
||||
assert_eq!(inner_payload.len(), 324);
|
||||
assert_eq!(inner_payload[35], 69);
|
||||
|
||||
assert_eq!(u128::from_be_bytes(inner_payload[20..36].try_into().unwrap()), market[0]);
|
||||
assert_eq!(u128::from_be_bytes(inner_payload[52..68].try_into().unwrap()), market[1]);
|
||||
assert_eq!(u128::from_be_bytes(inner_payload[84..100].try_into().unwrap()), market[2]);
|
||||
|
||||
assert_eq!(u128::from_be_bytes(inner_payload[116..132].try_into().unwrap()), terms[0]);
|
||||
assert_eq!(u128::from_be_bytes(inner_payload[148..164].try_into().unwrap()), terms[1]);
|
||||
|
||||
assert_eq!(&inner_payload[176..196], token.as_ref());
|
||||
|
||||
assert_eq!(u32::from_be_bytes(inner_payload[224..228].try_into().unwrap()), intervals[0]);
|
||||
assert_eq!(u32::from_be_bytes(inner_payload[256..260].try_into().unwrap()), intervals[1]);
|
||||
|
||||
assert_eq!(inner_payload[291], booleans[0] as u8);
|
||||
assert_eq!(inner_payload[323], booleans[1] as u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user