본문으로 건너뛰기

패키지 업그레이드

Sui smart contracts는 Move 모듈의 컬렉션으로 구성된 변경 불가능한 패키지 object이다. 패키지가 변경 불가능하기 때문에 transaction은 전체 합의 없이도 smart contract에 안전하게 접근할 수 있다(fastpath transactions). 만약 누군가 이러한 패키지를 변경할 수 있다면, 이는 shared objects가 되어 transaction을 완료하기 전에 전체 합의가 필요하다.

그러나 패키지 객체를 변경할 수 없다는 점은 코드 개발의 반복적인 특성을 고려할 때 문제가 된다. 빌더는 fastpath 트랜잭션의 이점을 계속 누리면서도 자신의 코드를 업데이트하고 다른 개발자의 변경 사항을 가져올 수 있는 능력이 필요하다. 다행히도 Sui 네트워크는 변경 불가능한 속성을 유지하면서 패키지를 업그레이드할 수 있는 메커니즘을 제공한다.

upgrade 고려 사항

패키지를 업그레이드하기 전에 고려해야 할 프로세스의 몇 가지 세부 사항이 있다.

예를 들어, 모듈 초기화 함수는 패키지 업그레이드 시 다시 실행되지 않는다. 초기 패키지를 게시할 때 Move는 게시 이벤트 시점에 패키지에 대해 정의한 init 함수를 한 번(그리고 오직 한 번만) 실행한다. 패키지의 이후 버전에 포함할 수 있는 모든 init 함수는 무시된다. 자세한 내용은 The Move Book의 Module Initializer를 참조한다.

앞서 언급했듯이 Sui 네트워크의 모든 패키지는 변경 불가능하다. 이것으로 인해 체인에서 오래된 패키지를 삭제할 수 없다. 그 결과, 다른 패키지가 업그레이드된 패키지의 이전 버전에 정의된 메서드와 타입에 접근하는 것을 막을 수 있는 것은 없다.

업그레이드 요구 사항

패키지를 업그레이드하려면 패키지가 다음 요구 사항을 충족해야 한다:

  • 업그레이드하려는 패키지에 대한 UpgradeTicket을 보유해야 한다. Sui 네트워크는 패키지를 게시할 때 UpgradeCap을 발급하며, 해당 UpgradeCap의 소유자는 UpgradeTicket을 발급할 수 있다. Sui Client CLI는 이 요구 사항을 자동으로 처리한다.
  • 변경 사항은 이전 버전과 레이아웃 호환성이 있어야 한다.
    • 기존 public 함수 시그니처는 동일하게 유지되어야 한다.
    • 기존 struct 레이아웃(struct ability 포함)은 동일하게 유지되어야 한다.
    • 새로운 struct와 함수를 추가할 수 있다.
    • 기존 함수(public 여부와 무관)의 제네릭 타입 제약을 제거할 수 있다.
    • 함수 구현을 변경할 수 있다.
    • public이 아닌 함수의 시그니처(friendentry 함수 시그니처 포함)를 변경할 수 있다.
정보

의존성이 있는 패키지를 보유하고 있고 해당 의존성이 업그레이드되더라도, 패키지는 자동으로 새로운 버전에 의존하지 않는다. 새로운 의존성을 가리키도록 하려면 자신의 패키지를 명시적으로 업그레이드해야 한다.

업그레이드

이전 요구 사항을 충족하는 패키지를 업그레이드하려면 다음 플래그에 대한 값을 제공하여 sui client upgrade 명령을 사용한다:

Beginning with the Sui v1.24.1 release, the --gas-budget option is no longer required for CLI commands.

  • --gas-budget: 네트워크가 트랜잭션을 취소하기 전에 소모될 수 있는 gas 단위의 최대 수이다.
  • --cap: UpgradeCap의 ID이다. 이 ID는 publish 명령의 반환값으로 제공된다.

Move 코드를 사용하여 패키지를 업그레이드하는 개발자는 사용자 정의 업그레이드 정책을 정의하기 위한 타입과 함수에 접근할 수 있다. 예를 들어 Move 개발자는 현재 패키지 소유자와 관계없이 패키지 업그레이드를 허용하지 않기를 원할 수 있다. 이러한 동작을 생성하기 위해 make_immutable function를 사용할 수 있다. UpgradeTicketUpgrade Receipt와 같은 사용 가능한 타입을 활용하는 더 고급 정책도 가능하며, 예시는 GitHub의 custom upgrade policy를 참조한다.

Sui Client CLI를 사용할 때 upgrade 명령은 업그레이드 다이제스트 생성, UpgradeCap을 사용한 업그레이드 승인으로 UpgradeTicket 획득, 그리고 업그레이드 성공 후 UpgradeReceiptUpgradeCap을 업데이트하는 작업을 처리한다. 이러한 프로세스에 대해 더 알아보려면 package module에 대한 Move 문서를 참조한다.

Migrating users to the latest version

기본적으로 사용자는 패키지의 이전 버전을 계속 사용하는 것을 선택할 수도 있다. 패키지 개발자로서 이러한 가능성을 인지하고 이를 고려해야 한다.

예를 들어, 원래 패키지에 increment 함수를 정의할 수 있다:

public fun increment(c: &mut Counter) {
c.value = c.value + 1;
}

그 다음 패키지 업그레이드에서는 increment 함수에 이벤트 발생을 추가할 수 있다:

public struct Progress has copy, drop {
reached: u64
}

public fun increment(c: &mut Counter) {
c.value = c.value + 1;

if (c.value % 100 == 0) {
event::emit(Progress { reached: c.value });
}
}

이전 버전과 업그레이드된 increment 함수를 호출하는 호출자가 혼재되어 있으면, 이전 함수는 Progress 이벤트를 인지하지 못하므로 프로세스가 실패한다.

함수 정의 불일치와 유사하게, 구조체의 원래 필드와 동기화된 상태로 유지되어야 하는 dynamic 필드를 유지 관리하는 과정에서도 문제에 직면할 수 있다. 이러한 문제를 해결하기 위해 업그레이드의 일부로 새로운 타입을 도입하고 사용자를 해당 타입으로 이전하여 하위 호환성을 깨뜨릴 수 있다. 예를 들어 소유권 증명과 같은 증명을 보여주기 위해 소유 객체를 사용하고 있고, 문제가 있는 코드를 해결하기 위해 패키지의 새 버전을 개발하는 경우 업그레이드된 패키지에 새로운 타입을 도입할 수 있다. 그런 다음 이전 객체를 새로운 객체로 교환하는 함수를 패키지에 추가할 수 있다. 로직이 새로운 타입을 가진 객체만 인식하므로 사용자가 사실상 업그레이드하도록 강제하게 된다.

사용자가 최신 패키지로 업데이트하도록 하는 또 다른 예로는 패키지에 장부 관리를 위한 공유 객체가 있는데, 해당 로직에 결함이 있어 기대한 대로 동작하지 않는 경우가 있다. 이전 예와 마찬가지로, 올바른 로직을 가진 업그레이드된 패키지에 정의된 객체만 사용자가 사용하도록 하려면 패키지 업그레이드에 새로운 타입과 마이그레이션 함수를 추가한다. 이 프로세스에는 두 개의 트랜잭션이 필요하며, 하나는 업그레이드를 위한 것이고 다른 하나는 기존 공유 객체를 대체하는 새로운 공유 객체를 설정하기 위해 업그레이드된 패키지에서 호출하는 것이다. 설정 함수를 보호하기 위해 패키지의 일부로 AdminCap 객체 또는 이와 유사한 것을 생성하여 패키지 소유자인 본인만 해당 함수를 시작할 수 있는 권한을 갖도록 해야 한다. 아마도 더 유용한 방법으로는 공유 객체에 플래그를 포함시켜 패키지 소유자인 본인이 해당 공유 객체의 활성화 상태를 전환할 수 있도록 할 수 있다. 마이그레이션을 수행하는 동안 온체인 public에서 해당 객체에 대한 접근을 방지하기 위해 활성화 상태를 확인하는 검사를 추가할 수 있다. 물론 이러한 플래그는 로직에 결함이 있는 객체를 의도적으로 개발하기 때문이 아니라, 향후 어느 시점에 이와 같은 마이그레이션을 수행할 가능성이 있다고 예상되는 경우에만 생성할 것이다.

Versioned 공유 객체

공유 객체를 포함하는 패키지를 생성할 때는 패키지의 모든 이전 버전이 온체인에 계속 존재한다는 점을 고려하여 처음부터 업그레이드와 버저닝을 염두에 두어야 한다. 유용한 패턴은 공유 객체에 버저닝을 도입하고 버전 검사를 사용하여 패키지의 함수에 대한 접근을 보호하는 것으로, 이를 통해 패키지의 최신 버전에만 공유 객체에 대한 접근을 제한할 수 있다.

앞서 살펴본 counter 예제는, 처음에는 다음과 같은 형태로 시작했을수도 있다:

module example::counter;

public struct Counter has key {
id: UID,
value: u64,
}

fun init(ctx: &mut TxContext) {
transfer::share_object(Counter {
id: object::new(ctx),
value: 0,
})
}

public fun increment(c: &mut Counter) {
c.value = c.value + 1;
}

이 패키지에 대한 업그레이드가 공유 객체에 대한 접근을 패키지의 최신 버전으로 제한할 수 있도록 하려면 다음을 수행해야 한다:

  1. 상수 VERSION에 모듈의 현재 버전을 추적한다.
  2. 새로운 version 필드에서 공유 객체인 Counter의 현재 버전을 추적한다.
  3. 권한이 필요한 호출을 보호하기 위해 AdminCap를 도입하고, 새로운 필드를 통해 Counter를 해당 AdminCap와 연결한다(이미 공유 객체 관리를 위한 유사한 타입이 있다면 이를 재사용할 수 있다). 이 cap은 공유 객체를 버전 간에 마이그레이션하는 호출을 보호하는 데 사용된다.
  4. 공유 객체에 접근하는 모든 함수의 엔트리를 해당 version이 패키지 VERSION과 일치하는지 확인하는 검사로 보호한다.

이러한 모든 아이디어를 통합한 업그레이드 인식 counter 모듈은 다음과 같다:

module example::counter;

/// Not the right admin for this counter
const ENotAdmin: u64 = 0;

/// Calling functions from the wrong package version
const EWrongVersion: u64 = 1;

// 1. Track the current version of the module
const VERSION: u64 = 1;

public struct Counter has key {
id: UID,
// 2. Track the current version of the shared object
version: u64,
// 3. Associate the `Counter` with its `AdminCap`
admin: ID,
value: u64,
}

public struct AdminCap has key {
id: UID,
}

fun init(ctx: &mut TxContext) {
let admin = AdminCap { id: object::new(ctx) };

transfer::share_object(Counter {
id: object::new(ctx),
version: VERSION,
admin: object::id(&admin),
value: 0,
});

transfer::transfer(admin, ctx.sender());
}

public fun increment(c: &mut Counter) {
// 4. Guard the entry of all functions that access the shared object
// with a version check.
assert!(c.version == VERSION, EWrongVersion);
c.value = c.value + 1;
}

이 패턴을 사용하여 모듈을 업그레이드하려면 업그레이드에 필요한 구현 변경 사항 외에도 두 가지 추가 변경을 수행해야 한다:

  1. 패키지의 VERSION을 증가시킨다.
  2. 공유 객체를 업그레이드하기 위해 migrate 함수를 도입한다.

다음 모듈은 앞서 논의한 대로 Progress 이벤트를 발생시키는 업그레이드된 counter이며, 관리자(AdminCap 보유자)가 이전 패키지 버전에서 카운터에 접근하는 것을 방지할 수 있는 도구도 제공한다:

module example::counter;

use sui::event;

/// Not the right admin for this counter
const ENotAdmin: u64 = 0;

/// Migration is not an upgrade
const ENotUpgrade: u64 = 1;

/// Calling functions from the wrong package version
const EWrongVersion: u64 = 2;

// 1. Bump the `VERSION` of the package.
const VERSION: u64 = 2;

public struct Counter has key {
id: UID,
version: u64,
admin: ID,
value: u64,
}

public struct AdminCap has key {
id: UID,
}

public struct Progress has copy, drop {
reached: u64,
}

fun init(ctx: &mut TxContext) {
let admin = AdminCap {
id: object::new(ctx),
};

transfer::share_object(Counter {
id: object::new(ctx),
version: VERSION,
admin: object::id(&admin),
value: 0,
});

transfer::transfer(admin, ctx.sender());
}

public fun increment(c: &mut Counter) {
assert!(c.version == VERSION, EWrongVersion);
c.value = c.value + 1;

if (c.value % 100 == 0) {
event::emit(Progress { reached: c.value })
}
}

// 2. Introduce a migrate function
entry fun migrate(c: &mut Counter, a: &AdminCap) {
assert!(c.admin == object::id(a), ENotAdmin);
assert!(c.version < VERSION, ENotUpgrade);
c.version = VERSION;
}

이 버전의 패키지로 업그레이드하려면 패키지 업그레이드를 수행한 다음 후속 트랜잭션에서 migrate 함수를 호출해야 한다. migrate 함수는 다음과 같은 점에 유의해야 한다:

  • entry 함수가며 public이 아니다. 이는 이후 업그레이드에서 해당 함수를 완전히 변경하거나(시그니처 변경 포함) 아예 제거하는 것을 가능하게 한다.
  • AdminCap을 인자로 받아 해당 ID가 마이그레이션되는 카운터의 ID와 일치하는지 확인함으로써 이를 권한이 필요한 작업으로 만든다.
  • 모듈의 버전이 실제로 해당 객체에 대한 업그레이드인지 확인하는 정상성 검사를 포함한다. 이는 업그레이드 전에 모듈 버전을 증가시키지 못하는 것과 같은 오류를 발견하는 데 도움이 된다.

업그레이드가 성공적으로 완료된 이후에는 이전 버전의 패키지에서 increment를 호출하면 버전 검사에서 중단되고, 이후 버전에서의 호출은 성공해야 한다.

Extensions

이 패턴은 공유 객체를 포함하는 업그레이드 가능한 패키지의 기초를 이루지만, 패키지의 요구 사항에 따라 여러 방식으로 확장할 수 있다:

  • 버전 제약 조건은 더 표현력 있게 만들 수 있다:
    • 단일 u64를 사용하는 대신, 버전을 String으로 지정하거나 상한과 하한의 쌍으로 지정할 수 있다.
    • 공유 객체에 dynamic 필드로 마커 타입을 추가하거나 제거함으로써 특정 함수 또는 함수 집합에 대한 접근을 제어할 수 있다.
  • migrate 함수는 더 정교하게 만들 수 있으며(공유 객체의 다른 필드를 수정하거나, dynamic 필드를 추가 또는 제거하거나, 여러 공유 객체를 동시에 마이그레이션하는 등).
  • 여러 트랜잭션에 걸쳐 실행되어야 하는 대규모 마이그레이션은 세 단계 설정으로 구현할 수 있다:
    • AdminCap으로 보호된 호출을 사용하여 공유 객체의 버전을 센티널 값(예: U64_MAX)으로 설정함으로써 일반적인 접근을 비활성화한다.
    • 여러 트랜잭션에 걸쳐 마이그레이션을 실행한다(예: 많은 양의 객체를 이동해야 하는 경우 트랜잭션 한도에 도달하는 것을 피하기 위해 배치로 수행하는 것이 가장 좋다).
    • 공유 객체의 버전을 다시 사용 가능한 값으로 설정한다.

예시

sui_package라는 이름의 패키지를 개발한다고 가정한다. 해당 매니페스트는 다음과 같다:

[package]
name = "sui_package"
version = "0.0.0"

[addresses]
sui_package = "0x0"

패키지가 준비되면 이를 게시한다:

$ sui client publish
Click to open

출력

INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING my_first_package
Successfully verified dependencies onchain against source.
Transaction Digest: GPSpH264CjQPaXQPpMHpkzyGidZnQFvd1yUH5s9ncesi
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: PUBLISHER-ID │
│ Gas Owner: PUBLISHER-ID │
│ Gas Budget: 12298000 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Version: 2 │
│ │ Digest: QDssxM4QKnhutWCYijiWWmYPtKWnHB9xVaLqPsDHiep │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Pure Arg: Type: address, Value: "PUBLISHER-ID" │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├─────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Publish: │ │
│ │ ┌ │ │
│ │ │ Dependencies: │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000001 │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ └ │ │
│ │ │ │
│ │ 1 TransferObjects: │ │
│ │ ┌ │ │
│ │ │ Arguments: │ │
│ │ │ Result 0 │ │
│ │ │ Address: Input 0 │ │
│ │ └ │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ 4NqP6CL1/LN1Ekr9NeL82PFGgVdEjrwsP82l/0mFvCd9TYO94CKBQAm8C/D6DsAuBrwu4cogQ3Mbh1huGc0yCg== │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: GPSpH264CjQPaXQPpMHpkzyGidZnQFvd1yUH5s9ncesi │
│ Status: Success │
│ Executed Epoch: 285 │
│ │
│ Created Objects: │
│ ┌── │
│ │ ID: ORIGINAL-PACKAGE-ID │
│ │ Owner: Immutable │
│ │ Version: 1 │
│ │ Digest: 4ZvhnDgehkRmzo3mtHjCc6aQkEz1SA87rDpDS6pGarFR │
│ └── │
│ ┌── │
│ │ ID: 0xaa06f409af7a36c20a552e729eb985a9979149ae9ada5ce3ed413836fd12ed16 │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 3 │
│ │ Digest: 71G4PuCUoqx1KDTnt8zGMYUf6Qpf4CWgZsDxYN1d7mXE │
│ └── │
│ ┌── │
│ │ ID: UPGRADE-CAP-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 3 │
│ │ Digest: FNxdiGCk1fwXByda6Q2sx8RjuwUQBFYQk7C4Zr2H4qVw │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 3 │
│ │ Digest: 9Fet6LPSBsjYjVMEQxkB4LRHfAJDFCQQ2iUAiUQ5eygF │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 3 │
│ │ Digest: 9Fet6LPSBsjYjVMEQxkB4LRHfAJDFCQQ2iUAiUQ5eygF │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 10298000 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 978120 MIST │
│ Non-refundable Storage Fee: 9880 MIST │
│ │
│ Transaction Dependencies: │
│ 3eHwwq6p2xQwBtXDE9KKNQwZFdHUGEKiJsR5LDmv4o7b │
│ 7KAuWTJHCZmh2rMSAqobkhU5cuRBoVicwae78i9woDUK │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯

╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0xaa06f409af7a36c20a552e729eb985a9979149ae9ada5ce3ed413836fd12ed16 │
│ │ Sender: PUBLISHER-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ ObjectType: ORIGINAL-PACKAGE-ID::module::TYPE │
│ │ Version: 3 │
│ │ Digest: 71G4PuCUoqx1KDTnt8zGMYUf6Qpf4CWgZsDxYN1d7mXE │
│ └── │
│ ┌── │
│ │ ObjectID: UPGRADE-CAP-ID │
│ │ Sender: PUBLISHER-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 3 │
│ │ Digest: FNxdiGCk1fwXByda6Q2sx8RjuwUQBFYQk7C4Zr2H4qVw │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: GAS-COIN-ID │
│ │ Sender: PUBLISHER-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 3 │
│ │ Digest: 9Fet6LPSBsjYjVMEQxkB4LRHfAJDFCQQ2iUAiUQ5eygF │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: ORIGINAL-PACKAGE-ID │
│ │ Version: 1 │
│ │ Digest: 4ZvhnDgehkRmzo3mtHjCc6aQkEz1SA87rDpDS6pGarFR │
│ │ Modules: example │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -10319880 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯

결과에는 업그레이드에 필요한 두 가지 정보인 UpgradeCap ID와 패키지 ID를 포함한 Object changes 섹션이 포함된다.

응답에서 Object.objectType 값을 사용하여 서로 다른 객체를 식별할 수 있다. UpgradeCap 항목은 String("0x2::package::UpgradeCap") 값을 가지며, 패키지에 대한 objectTypeString("<PACKAGE-ID>::sui_package::<MODULE-NAME>")로 표시된다.

정보

Sui v1.29.0 릴리스부터 게시된 주소는 Move.lock 파일에서 자동으로 관리되며, 추가로 수행해야 할 작업은 없다.

패키지가 v1.29.0 이전의 Sui 버전으로 게시되거나 업그레이드된 경우, the guide for adopting automated address management를 따를 수 있다. 또는 추가 단계에 대해서는 위의 Manual Addresses 탭을 참조한다.

시간이 지난 후 요청된 일부 기능을 포함하기 위해 sui_package를 업그레이드하기로 결정한다.

패키지를 업그레이드하려면 sui client upgrade 명령을 실행한다. 예시의 <UPGRADE-CAP-ID> 값인 UpgradeCap ID를 --upgrade-capability 플래그에 전달한다.

$ sui client upgrade --upgrade-capability <UPGRADE-CAP-ID>

새 패키지가 업그레이드 요구 사항을 충족하지 않으면 콘솔이 이를 알리며, 그렇지 않으면 컴파일러가 업그레이드된 패키지를 네트워크에 게시하고 그 결과를 반환한다.

Click to open
출력
Transaction Digest: 3NnJGryz2k2BJzjpndDVqVcdZmmefNMB8SJ9bCEQct22
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: PUBLISHER-ID │
│ Gas Owner: PUBLISHER-ID │
│ Gas Budget: 9684740 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Version: 3 │
│ │ Digest: D2rpccs7eSw8gtb4T1K2bSVzF5eApC68xiHDtNGQEcEb │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Imm/Owned Object ID: UPGRAD-CAP-ID │ │
│ │ 1 Pure Arg: Type: u8, Value: 0 │ │
│ │ 2 Pure Arg: Type: vector<u8>, Value: [49,208,61,255,107,134,136,221,231,35,60,2,248,17,234,236,64,76,71,188,57,104,46,113,67,94,232,236,64,59,144,112] │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├───────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 MoveCall: │ │
│ │ ┌ │ │
│ │ │ Function: authorize_upgrade │ │
│ │ │ Module: package │ │
│ │ │ Package: 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ │ Arguments: │ │
│ │ │ Input 0 │ │
│ │ │ Input 1 │ │
│ │ │ Input 2 │ │
│ │ └ │ │
│ │ │ │
│ │ 1 Upgrade: │ │
│ │ ┌ │ │
│ │ │ Dependencies: │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000001 │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ │ Current Package ID: ORIGINAL-PACKAGE-ID │ │
│ │ │ Ticket: Result 0 │ │
│ │ └ │ │
│ │ │ │
│ │ 2 MoveCall: │ │
│ │ ┌ │ │
│ │ │ Function: commit_upgrade │ │
│ │ │ Module: package │ │
│ │ │ Package: 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ │ Arguments: │ │
│ │ │ Input 0 │ │
│ │ │ Result 1 │ │
│ │ └ │ │
│ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ nNJ8AiSAeV+NB3ayRTwcfaJHx3AzFHlZysbwda5e2jFBz5W9Z5EnzXV09xZMQYctUtW33jWpUFdK8hOJ9hZzDg== │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: 3NnJGryz2k2BJzjpndDVqVcdZmmefNMB8SJ9bCEQct22 │
│ Status: Success │
│ Executed Epoch: 1 │
│ │
│ Created Objects: │
│ ┌── │
│ │ ID: 0x5d49966433ebb423f5b40bfcd0ecfdc67f1527e3b9e3a433c4ec87ae63d54ed4 │
│ │ Owner: Immutable │
│ │ Version: 2 │
│ │ Digest: 6GmLYmCszFxbaLRLTyZdxTTfXG99iq8uVabfi2NaB5fQ │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 4 │
│ │ Digest: G5PBJjLKJWL2J3rb8ZR4uLNgFPpyJNNXfXNoh3FDo1zK │
│ └── │
│ ┌── │
│ │ ID: 0x562408a381f3f2fce9c5ea27da42953e001760aa35dbadb273dca24166657516 │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 4 │
│ │ Digest: 6B4pA1EcYek2pvrRoBv9jKhPmUGxhH1zZD3UcqPmxwDM │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: GAS-COIN-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ Version: 4 │
│ │ Digest: G5PBJjLKJWL2J3rb8ZR4uLNgFPpyJNNXfXNoh3FDo1zK │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 9302400 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 2595780 MIST │
│ Non-refundable Storage Fee: 26220 MIST │
│ │
│ Transaction Dependencies: │
│ 7MdLdLYBhP6LKGf6gvuona2EQJZ1W7k3kRisrapmzQ5m │
│ 8etH8jq78aKDHwL9ZnmAMhra62Q9vcPfyAcKJyXNPWvi │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯

╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: GAS-COIN-ID │
│ │ Sender: PUBLISHER-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 4 │
│ │ Digest: G5PBJjLKJWL2J3rb8ZR4uLNgFPpyJNNXfXNoh3FDo1zK │
│ └── │
│ ┌── │
│ │ ObjectID: 0x562408a381f3f2fce9c5ea27da42953e001760aa35dbadb273dca24166657516 │
│ │ Sender: PUBLISHER-ID │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 4 │
│ │ Digest: 6B4pA1EcYek2pvrRoBv9jKhPmUGxhH1zZD3UcqPmxwDM │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0x5d49966433ebb423f5b40bfcd0ecfdc67f1527e3b9e3a433c4ec87ae63d54ed4 │
│ │ Version: 2 │
│ │ Digest: 6GmLYmCszFxbaLRLTyZdxTTfXG99iq8uVabfi2NaB5fQ │
│ │ Modules: example │
│ └── │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( PUBLISHER-ID ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -7706620 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯

결과는 업그레이드된 패키지에 대한 새로운 ID를 제공한다.

정보

Sui v1.29.0 릴리스부터 업그레이드된 주소는 Move.lock 파일에서 자동으로 관리되며, 추가로 수행해야 할 작업은 없다.

패키지가 v1.29.0 이전의 Sui 버전으로 게시되거나 업그레이드된 경우, 자동 주소 관리 채택을 위한 가이드를 따를 수 있다. 또는 추가 단계에 대해서는 위의 Manual Addresses 탭을 참조한다.