// A minimized version of the MarketCap verification problem. address 0x1 { module TestMarketCapWithSchemas { /* TODO(refactoring): this test is deactivated until we have ported this (or a similar) feature, or decided to drop it in which case the test should be removed. spec module { pragma verify = true; } spec module { global sum_of_coins: num; } spec schema SumOfCoinsModuleInvariant { invariant module global(0xA550C18).total_value == sum_of_coins; } spec module { // This is the statement we are actually testing here. Expectation is that the invariant above // is woven into any public function with one type parameter except it's name starts with // `excepted_`. apply SumOfCoinsModuleInvariant to public *deposit* except excepted_*; } // A resource representing the Diem coin resource struct T { // The value of the coin. May be zero value: u64, } spec T { invariant pack sum_of_coins = sum_of_coins + value; invariant unpack sum_of_coins = sum_of_coins - value; } resource struct MarketCap { // The sum of the values of all DiemCoin::T resources in the system total_value: u128, } // A schema for deposit functions which match the module invariant. spec schema DepositCorrect { coin_ref: &mut T; check: T; aborts_if coin_ref.value + check.value > max_u64(); ensures coin_ref.value == old(coin_ref.value) + check.value; } // A schema for deposit functions which do NOT match the module invariant. spec schema DepositIncorrect { coin_ref: &mut T; check: T; aborts_if coin_ref.value + check.value / 2 > max_u64(); ensures coin_ref.value == old(coin_ref.value) + check.value / 2; } // A function which matches the schema apply and which satisfies the invariant. public fun deposit(coin_ref: &mut T, check: T) { let T { value } = check; coin_ref.value = coin_ref.value + value; } spec deposit { include DepositCorrect; } // A function which matches the schema apply and which does NOT satisfies the invariant. public fun deposit_incorrect(coin_ref: &mut T, check: T) { let T { value } = check; coin_ref.value = coin_ref.value + value / 2; } spec deposit_incorrect { include DepositIncorrect; } // A function which does NOT match the schema apply and which does NOT satisfies the invariant. // It does not match because it is not public. fun deposit_not_public(coin_ref: &mut T, check: T) { let T { value } = check; coin_ref.value = coin_ref.value + value / 2; } spec deposit_not_public { include DepositIncorrect; } // A function which does NOT match the schema apply and which does NOT satisfies the invariant. // It does not match because it's name starts with `excepted_`. public fun excepted_deposit(coin_ref: &mut T, check: T) { let T { value } = check; coin_ref.value = coin_ref.value + value / 2; } spec excepted_deposit { include DepositIncorrect; } // A function which does NOT match the schema apply and which does NOT satisfies the invariant. // It does not match because it has a different type parameter arity. public fun deposit_different_type_params(coin_ref: &mut T, check: T) { let T { value } = check; coin_ref.value = coin_ref.value + value / 2; } spec deposit_different_type_params { include DepositIncorrect; } */ } }