Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax key + store constraint in TransferRequest and TransferRequest type parameter T #9604

Closed
wants to merge 5 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Relax key + store contraint in generic parameter T
  • Loading branch information
kaizu-xyz committed Mar 22, 2023
commit 286a96f5978d859d12ee021cc2fdd19bc824dcf2
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module sui::transfer_policy {

/// A "Hot Potato" forcing the buyer to get a transfer permission
/// from the item type (`T`) owner on purchase attempt.
struct TransferRequest<phantom T: key + store> {
struct TransferRequest<phantom T> {
/// Amount of SUI paid for the item. Can be used to
/// calculate the fee / transfer policy enforcement.
paid: u64,
Expand All @@ -54,7 +54,7 @@ module sui::transfer_policy {

/// A unique capability that allows owner of the `T` to authorize
/// transfers. Can only be created with the `Publisher` object.
struct TransferPolicy<phantom T: key + store> has key, store {
struct TransferPolicy<phantom T> has key, store {
id: UID,
/// The Balance of the `TransferPolicy` which collects `SUI`.
/// By default, transfer policy does not collect anything , and it's
Expand All @@ -67,21 +67,21 @@ module sui::transfer_policy {

/// A Capability granting the owner permission to add/remove rules as well
/// as to `withdraw` and `destroy_and_withdraw` the `TransferPolicy`.
struct TransferPolicyCap<phantom T: key + store> has key, store {
struct TransferPolicyCap<phantom T> has key, store {
id: UID,
policy_id: ID
}

/// Event that is emitted when a publisher creates a new `TransferPolicyCap`
/// making the discoverability and tracking the supported types easier.
struct TransferPolicyCreated<phantom T: key + store> has copy, drop { id: ID }
struct TransferPolicyCreated<phantom T> has copy, drop { id: ID }

/// Key to store "Rule" configuration for a specific `TransferPolicy`.
struct RuleKey<phantom T: drop> has copy, store, drop {}

/// Construct a new `TransferRequest` hot potato which requires an
/// approving action from the creator to be destroyed / resolved.
public fun new_request<T: key + store>(
public fun new_request<T>(
paid: u64, from: ID, ctx: &mut TxContext
): TransferRequest<T> {
TransferRequest {
Expand All @@ -93,7 +93,7 @@ module sui::transfer_policy {
/// which is required to confirm kiosk deals for the `T`. If there's no
/// `TransferPolicyCap` available for use, the type can not be traded in
/// kiosks.
public fun new<T: key + store>(
public fun new<T>(
pub: &Publisher, ctx: &mut TxContext
): (TransferPolicy<T>, TransferPolicyCap<T>) {
assert!(package::from_package<T>(pub), 0);
Expand All @@ -112,7 +112,7 @@ module sui::transfer_policy {
/// type without a `Publisher` object. Is not magical and a similar logic
/// can be implemented for the regular `new_transfer_policy_cap` call for
/// wrapped types.
public(friend) fun new_protected<T: key + store>(
public(friend) fun new_protected<T>(
ctx: &mut TxContext
): (TransferPolicy<T>, TransferPolicyCap<T>) {
let id = object::new(ctx);
Expand All @@ -128,7 +128,7 @@ module sui::transfer_policy {

/// Withdraw some amount of profits from the `TransferPolicy`. If amount is not
/// specified, all profits are withdrawn.
public fun withdraw<T: key + store>(
public fun withdraw<T>(
self: &mut TransferPolicy<T>, cap: &TransferPolicyCap<T>, amount: Option<u64>, ctx: &mut TxContext
): Coin<SUI> {
assert!(object::id(self) == cap.policy_id, ENotOwner);
Expand All @@ -146,7 +146,7 @@ module sui::transfer_policy {

/// Destroy a TransferPolicyCap.
/// Can be performed by any party as long as they own it.
public fun destroy_and_withdraw<T: key + store>(
public fun destroy_and_withdraw<T>(
self: TransferPolicy<T>, cap: TransferPolicyCap<T>, ctx: &mut TxContext
): Coin<SUI> {
assert!(object::id(&self) == cap.policy_id, ENotOwner);
Expand All @@ -165,7 +165,7 @@ module sui::transfer_policy {
///
/// Note: unless there's a policy for `T` to allow transfers,
/// Kiosk trades will not be possible.
public fun confirm_request<T: key + store>(
public fun confirm_request<T>(
self: &TransferPolicy<T>, request: TransferRequest<T>
): (u64, ID) {
let TransferRequest { paid, from, receipts, metadata } = request;
Expand Down Expand Up @@ -195,7 +195,7 @@ module sui::transfer_policy {
///
/// Config requires `drop` to allow creators to remove any policy at any moment,
/// even if graceful unpacking has not been implemented in a "rule module".
public fun add_rule<T: key + store, Rule: drop, Config: store + drop>(
public fun add_rule<T, Rule: drop, Config: store + drop>(
_: Rule, policy: &mut TransferPolicy<T>, cap: &TransferPolicyCap<T>, cfg: Config
) {
assert!(object::id(policy) == cap.policy_id, ENotOwner);
Expand All @@ -205,14 +205,14 @@ module sui::transfer_policy {
}

/// Get the custom Config for the Rule (can be only one per "Rule" type).
public fun get_rule<T: key + store, Rule: drop, Config: store + drop>(
public fun get_rule<T, Rule: drop, Config: store + drop>(
_: Rule, policy: &TransferPolicy<T>)
: &Config {
df::borrow(&policy.id, RuleKey<Rule> {})
}

/// Add some `SUI` to the balance of a `TransferPolicy`.
public fun add_to_balance<T: key + store, Rule: drop>(
public fun add_to_balance<T, Rule: drop>(
_: Rule, policy: &mut TransferPolicy<T>, coin: Coin<SUI>
) {
assert!(has_rule<T, Rule>(policy), EUnknownRequrement);
Expand All @@ -221,19 +221,19 @@ module sui::transfer_policy {

/// Adds a `Receipt` to the `TransferRequest`, unblocking the request and
/// confirming that the policy requirements are satisfied.
public fun add_receipt<T: key + store, Rule: drop>(
public fun add_receipt<T, Rule: drop>(
_: Rule, request: &mut TransferRequest<T>
) {
vec_set::insert(&mut request.receipts, type_name::get<Rule>())
}

/// Check whether a custom rule has been added to the `TransferPolicy`.
public fun has_rule<T: key + store, Rule: drop>(policy: &TransferPolicy<T>): bool {
public fun has_rule<T, Rule: drop>(policy: &TransferPolicy<T>): bool {
df::exists_(&policy.id, RuleKey<Rule> {})
}

/// Remove the Rule from the `TransferPolicy`.
public fun remove_rule<T: key + store, Rule: drop, Config: store + drop>(
public fun remove_rule<T, Rule: drop, Config: store + drop>(
policy: &mut TransferPolicy<T>, cap: &TransferPolicyCap<T>
) {
assert!(object::id(policy) == cap.policy_id, ENotOwner);
Expand All @@ -243,13 +243,13 @@ module sui::transfer_policy {
// === Fields access ===

/// Get the `paid` field of the `TransferRequest`.
public fun paid<T: key + store>(self: &TransferRequest<T>): u64 { self.paid }
public fun paid<T>(self: &TransferRequest<T>): u64 { self.paid }

/// Get the `from` field of the `TransferRequest`.
public fun from<T: key + store>(self: &TransferRequest<T>): ID { self.from }
public fun from<T>(self: &TransferRequest<T>): ID { self.from }

/// Get the `metadata_mut` field of the `TransferRequest`.
public fun metadata_mut<T: key + store>(self: &mut TransferRequest<T>): &mut Bag { &mut self.metadata }
public fun metadata_mut<T>(self: &mut TransferRequest<T>): &mut Bag { &mut self.metadata }
}

#[test_only]
Expand All @@ -276,7 +276,7 @@ module sui::fixed_commission {

/// Creator action: adds a Rule;
/// Set a FixedCommission requirement for the TransferPolicy.
public fun set<T: key + store>(
public fun set<T>(
policy: &mut TransferPolicy<T>,
cap: &TransferPolicyCap<T>,
amount: u64
Expand All @@ -286,13 +286,13 @@ module sui::fixed_commission {

/// Creator action: remove the rule from the policy.
/// Can be performed freely at any time, this method only helps fill-in type params.
public fun unset<T: key + store>(policy: &mut TransferPolicy<T>, cap: &TransferPolicyCap<T>) {
public fun unset<T>(policy: &mut TransferPolicy<T>, cap: &TransferPolicyCap<T>) {
policy::remove_rule<T, Rule, Commission>(policy, cap)
}

/// Buyer action: perform required action;
/// Complete the requirement on `TransferRequest`. In this case - pay the fixed fee.
public fun pay<T: key + store>(
public fun pay<T>(
policy: &mut TransferPolicy<T>, request: &mut TransferRequest<T>, coin: Coin<SUI>
) {
let paid = policy::paid(request);
Expand All @@ -319,14 +319,14 @@ module sui::dummy_policy {
struct Rule has drop {}
struct Config has store, drop {}

public fun set<T: key + store>(
public fun set<T>(
policy: &mut TransferPolicy<T>,
cap: &TransferPolicyCap<T>
) {
policy::add_rule(Rule {}, policy, cap, Config {})
}

public fun pay<T: key + store>(
public fun pay<T>(
policy: &mut TransferPolicy<T>,
request: &mut TransferRequest<T>,
payment: Coin<SUI>
Expand All @@ -342,7 +342,7 @@ module sui::malicious_policy {

struct Rule has drop {}

public fun cheat<T: key + store>(request: &mut TransferRequest<T>) {
public fun cheat<T>(request: &mut TransferRequest<T>) {
policy::add_receipt(Rule {}, request);
}
}
Expand Down