Skip to content

pallet-storage-provider: transfer_agreement_ownership - #405

Open
ilchu wants to merge 7 commits into
ic/drive-share-authfrom
ic/agreement-transfer
Open

pallet-storage-provider: transfer_agreement_ownership#405
ilchu wants to merge 7 commits into
ic/drive-share-authfrom
ic/agreement-transfer

Conversation

@ilchu

@ilchu ilchu commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

The implementation design has specified transfer_agreement_ownership since the start, the event for it was declared from day one, and the gap analysis in #1 counted the event as the feature. Nothing was ever built; #376 tracks it as DRIFT-015 with the proposal "implement". This does that.

Owner only. It hands the agreement to new_owner, who can then top up, extend, settle, or transfer it again. The escrow moves with the owner: the prepaid fee and, for a replica, the unspent sync balance are held on the owner's account and every settlement path draws on that hold, so the new move_escrow helper transfers the held amount on hold to the new owner in one step. The try-state invariant that holds match per-owner bookkeeping keeps passing. Transferring to oneself is rejected rather than treated as a no-op, so a transfer event always means a change of hands.

Rust and TypeScript SDK wrappers mirror the other agreement calls, and the extensions e2e suite gains a step that transfers Bob's agreement to Charlie and checks that top-up follows the owner. Bindings are regenerated.

Weights are hand-written estimates in the pallet and both runtimes so the runtimes build. Run /cmd bench --pallet pallet_storage_provider on this PR to replace them with measured values.

Layer 1 after a transfer. The escrow follows the agreement owner by construction: cleanup_bucket_internal refunds each agreement to its own owner and uses the caller only for the admin check, so delete_drive keeps working for the drive owner and the unspent escrow goes to whoever owns the agreement now. The one loose end was the DriveDeleted event, which paired the drive owner with a refunded amount that may have gone to someone else; the field is now escrow_released, documented as going to the agreements' owners. S3 is unaffected: delete_s3_bucket never touches Layer 0, so it reads neither owner. That S3 leaves the agreement running on delete while drives settle it is a separate inconsistency worth its own issue.

@ilchu

ilchu commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator Author

/cmd bench --pallet pallet_storage_provider pallet_s3_registry pallet_drive_registry

@command-bot-web3-storage

Copy link
Copy Markdown

Command "bench --pallet pallet_storage_provider pallet_s3_registry pallet_drive_registry" has started 🚀 See logs here

@ilchu ilchu self-assigned this Sep 10, 2026
@ilchu
ilchu added this pull request to stack #407 September 10, 2026 11:56
@command-bot-web3-storage

Copy link
Copy Markdown

Command "bench --pallet pallet_storage_provider pallet_s3_registry pallet_drive_registry" has finished ✅ See logs here

Details

Subweight results:
File Extrinsic Old New Change [%]
runtimes/web3-storage-paseo/src/weights/pallet_storage_provider.rs transfer_agreement_ownership 696.85us Added
runtimes/web3-storage-local/src/weights/pallet_storage_provider.rs transfer_agreement_ownership 698.77us Added
crates/pallets/storage-provider/src/weights.rs transfer_agreement_ownership 655.00us Added
Command output:

args: Namespace(command='bench', continue_on_fail=False, quiet=False, clean=False, runtime=['web3-storage-paseo', 'storage-parachain-runtime'], pallet=['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry'], steps=50, repeat=20, profile='production')
Created temp dir: /tmp/tmp10k7uwjj
Provided runtimes: ['web3-storage-paseo', 'storage-parachain-runtime']
Cargo profile: production
Filtered out runtimes: {'web3-storage-paseo': {'name': 'web3-storage-paseo', 'package': 'storage-paseo-runtime', 'path': 'runtimes/web3-storage-paseo', 'build_command': 'build-paseo-runtime', 'zombienet_config': 'zombienet/storage-paseo-local.toml', 'chain_spec_script': 'scripts/build-paseo-chain-spec.sh', 'uris': ['wss://previewnet.substrate.dev/web3-storage'], 'integration_tests': True, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}, 'storage-parachain-runtime': {'name': 'storage-parachain-runtime', 'package': 'storage-parachain-runtime', 'path': 'runtimes/web3-storage-local', 'build_command': 'build-runtime', 'zombienet_config': 'zombienet/zombienet-parachain-local.toml', 'chain_spec_script': 'scripts/build-chain-spec.sh', 'uris': ['TODO: update WSS'], 'integration_tests': False, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}}
-- compiling the runtime web3-storage-paseo
-- listing pallets for benchmark for web3-storage-paseo
frame-omni-bencher v1 benchmark pallet --no-csv-header --all --list --runtime=target/production/wbuild/storage-paseo-runtime/storage_paseo_runtime.wasm
Pallets in {'name': 'web3-storage-paseo', 'package': 'storage-paseo-runtime', 'path': 'runtimes/web3-storage-paseo', 'build_command': 'build-paseo-runtime', 'zombienet_config': 'zombienet/storage-paseo-local.toml', 'chain_spec_script': 'scripts/build-paseo-chain-spec.sh', 'uris': ['wss://previewnet.substrate.dev/web3-storage'], 'integration_tests': True, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}: ['pallet_balances', 'frame_system_extensions', 'pallet_message_queue', 'cumulus_pallet_parachain_system', 'frame_system', 'pallet_storage_provider', 'pallet_xcm_benchmarks::fungible', 'pallet_timestamp', 'pallet_xcm', 'pallet_collator_selection', 'pallet_transaction_payment', 'pallet_s3_registry', 'pallet_revive', 'pallet_drive_registry', 'pallet_session', 'pallet_xcm_benchmarks::generic', 'cumulus_pallet_xcmp_queue', 'cumulus_pallet_weight_reclaim', 'pallet_sudo', 'pallet_utility']
-- compiling the runtime storage-parachain-runtime
-- listing pallets for benchmark for storage-parachain-runtime
frame-omni-bencher v1 benchmark pallet --no-csv-header --all --list --runtime=target/production/wbuild/storage-parachain-runtime/storage_parachain_runtime.wasm
Pallets in {'name': 'storage-parachain-runtime', 'package': 'storage-parachain-runtime', 'path': 'runtimes/web3-storage-local', 'build_command': 'build-runtime', 'zombienet_config': 'zombienet/zombienet-parachain-local.toml', 'chain_spec_script': 'scripts/build-chain-spec.sh', 'uris': ['TODO: update WSS'], 'integration_tests': False, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}: ['pallet_balances', 'frame_system_extensions', 'pallet_message_queue', 'cumulus_pallet_parachain_system', 'frame_system', 'pallet_storage_provider', 'pallet_xcm_benchmarks::fungible', 'pallet_timestamp', 'pallet_xcm', 'pallet_collator_selection', 'pallet_transaction_payment', 'pallet_s3_registry', 'pallet_revive', 'pallet_drive_registry', 'pallet_session', 'pallet_xcm_benchmarks::generic', 'cumulus_pallet_xcmp_queue', 'cumulus_pallet_weight_reclaim', 'pallet_sudo', 'pallet_utility']
Pallet: ['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry']
Filtered out runtimes & pallets: {'web3-storage-paseo': ['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry'], 'storage-parachain-runtime': ['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry']}
-- config: {'name': 'web3-storage-paseo', 'package': 'storage-paseo-runtime', 'path': 'runtimes/web3-storage-paseo', 'build_command': 'build-paseo-runtime', 'zombienet_config': 'zombienet/storage-paseo-local.toml', 'chain_spec_script': 'scripts/build-paseo-chain-spec.sh', 'uris': ['wss://previewnet.substrate.dev/web3-storage'], 'integration_tests': True, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_storage_provider in web3-storage-paseo into ./runtimes/web3-storage-paseo/src/weights using template None
-- config: {'name': 'web3-storage-paseo', 'package': 'storage-paseo-runtime', 'path': 'runtimes/web3-storage-paseo', 'build_command': 'build-paseo-runtime', 'zombienet_config': 'zombienet/storage-paseo-local.toml', 'chain_spec_script': 'scripts/build-paseo-chain-spec.sh', 'uris': ['wss://previewnet.substrate.dev/web3-storage'], 'integration_tests': True, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_s3_registry in web3-storage-paseo into ./runtimes/web3-storage-paseo/src/weights using template None
-- config: {'name': 'web3-storage-paseo', 'package': 'storage-paseo-runtime', 'path': 'runtimes/web3-storage-paseo', 'build_command': 'build-paseo-runtime', 'zombienet_config': 'zombienet/storage-paseo-local.toml', 'chain_spec_script': 'scripts/build-paseo-chain-spec.sh', 'uris': ['wss://previewnet.substrate.dev/web3-storage'], 'integration_tests': True, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_drive_registry in web3-storage-paseo into ./runtimes/web3-storage-paseo/src/weights using template None
-- config: {'name': 'storage-parachain-runtime', 'package': 'storage-parachain-runtime', 'path': 'runtimes/web3-storage-local', 'build_command': 'build-runtime', 'zombienet_config': 'zombienet/zombienet-parachain-local.toml', 'chain_spec_script': 'scripts/build-chain-spec.sh', 'uris': ['TODO: update WSS'], 'integration_tests': False, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_storage_provider in storage-parachain-runtime into ./runtimes/web3-storage-local/src/weights using template None
-- config: {'name': 'storage-parachain-runtime', 'package': 'storage-parachain-runtime', 'path': 'runtimes/web3-storage-local', 'build_command': 'build-runtime', 'zombienet_config': 'zombienet/zombienet-parachain-local.toml', 'chain_spec_script': 'scripts/build-chain-spec.sh', 'uris': ['TODO: update WSS'], 'integration_tests': False, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_s3_registry in storage-parachain-runtime into ./runtimes/web3-storage-local/src/weights using template None
-- config: {'name': 'storage-parachain-runtime', 'package': 'storage-parachain-runtime', 'path': 'runtimes/web3-storage-local', 'build_command': 'build-runtime', 'zombienet_config': 'zombienet/zombienet-parachain-local.toml', 'chain_spec_script': 'scripts/build-chain-spec.sh', 'uris': ['TODO: update WSS'], 'integration_tests': False, 'try_runtime': {'spec_name_check': '--disable-spec-name-check', 'extra_flags': '--blocktime 6000 --disable-spec-version-check'}, 'benchmarks_templates': {'pallet_xcm_benchmarks::generic': 'templates/xcm-bench-template.hbs', 'pallet_xcm_benchmarks::fungible': 'templates/xcm-bench-template.hbs'}}
-- benchmarking pallet_drive_registry in storage-parachain-runtime into ./runtimes/web3-storage-local/src/weights using template None
✅ Successful benchmarks of runtimes/pallets:
-- web3-storage-paseo: ['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry']
-- storage-parachain-runtime: ['pallet_storage_provider', 'pallet_s3_registry', 'pallet_drive_registry']
🚀 Done

ilchu and others added 7 commits September 10, 2026 21:47
The design has specified this call since the start and the event for
it was declared from day one, but nothing was ever built; the gap
analysis even counted the event as the feature. Owner only: hands the
agreement to `new_owner`, who can then top up, extend, settle, or
transfer it again.

The escrow moves with the owner. The prepaid fee and, for a replica,
the unspent sync balance are held on the owner's account and every
settlement path draws on that hold, so `move_escrow` transfers the
held amount on hold to the new owner in one step. The try-state
invariant that holds match per-owner bookkeeping keeps passing.

Transferring to oneself is rejected rather than treated as a no-op,
so a transfer event always means a change of hands.

The replica-provider test helper moves from the holds tests to the
shared test module so the transfer tests can use it.
The weight entries in the pallet and both runtimes are hand-written
estimates so the runtimes build; `/cmd bench` on the PR replaces them
with measured values.
Rust and TypeScript wrappers mirror the other agreement calls. The
extensions e2e suite gains a step that transfers Bob's agreement to
Charlie, then checks that top-up follows the owner: Bob is refused
with NotAgreementOwner and Charlie succeeds.
…fund

cleanup_bucket_internal refunds each agreement to its own owner and
uses the caller only for the admin check. Once an agreement can change
hands, the drive owner named in the event and the account that got the
money can differ, so the `refunded` field, documented as returned to
the owner, became misleading. It is now `escrow_released` and says
where the funds go. No consumer read the old field; the drive UI and
SDK only read `drive_id` and `owner`.
…t_storage_provider pallet_s3_registry pallet_drive_registry'
@ilchu
ilchu force-pushed the ic/agreement-transfer branch from 73e607d to 76a6a59 Compare September 10, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant